diff --git a/.gitignore b/.gitignore index 9ed24b542e..1a5bb29ad5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,9 @@ *.swp *.ver *.version +*.metal.air +*.metallib +*.metallib.c *.ptx *.ptx.c *.ptx.gz diff --git a/Changelog b/Changelog index d806b96253..3dde3326be 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,9 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version : + + +version 5.0: - ADPCM IMA Westwood encoder - Westwood AUD muxer - ADPCM IMA Acorn Replay decoder @@ -29,6 +32,22 @@ version : - limitdiff video filter - xcorrelate video filter - varblur video filter +- huesaturation video filter +- colorspectrum source video filter +- RTP packetizer for uncompressed video (RFC 4175) +- bitpacked encoder +- VideoToolbox VP9 hwaccel +- VideoToolbox ProRes hwaccel +- support loongarch. +- aspectralstats audio filter +- adynamicsmooth audio filter +- libplacebo filter +- vflip_vulkan, hflip_vulkan and flip_vulkan filters +- adynamicequalizer audio filter +- yadif_videotoolbox filter +- VideoToolbox ProRes encoder +- anlmf audio filter +- IMF demuxer (experimental) version 4.4: diff --git a/MAINTAINERS b/MAINTAINERS index dcac46003e..c065e94498 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -226,7 +226,7 @@ Codecs: ptx.c Ivo van Poorten qcelp* Reynaldo H. Verdejo Pinochet qdm2.c, qdm2data.h Roberto Togni - qsv* Mark Thompson, Zhong Li + qsv* Mark Thompson, Zhong Li, Haihao Xiang qtrle.c Mike Melanson ra144.c, ra144.h, ra288.c, ra288.h Roberto Togni resample2.c Michael Niedermayer @@ -274,8 +274,8 @@ Hardware acceleration: dxva2* Hendrik Leppkes, Laurent Aimar, Steve Lhomme d3d11va* Steve Lhomme mediacodec* Matthieu Bouron, Aman Gupta - vaapi* Gwenole Beauchesne - vaapi_encode* Mark Thompson + vaapi* Haihao Xiang + vaapi_encode* Mark Thompson, Haihao Xiang vdpau* Philip Langdale, Carl Eugen Hoyos videotoolbox* Rick Kern, Aman Gupta @@ -611,6 +611,7 @@ Daniel Verkamp 78A6 07ED 782C 653E C628 B8B9 F0EB 8DD8 2F0E 21C7 FFmpeg release signing key FCF9 86EA 15E6 E293 A564 4F10 B432 2F04 D676 58D8 Ganesh Ajjanagadde C96A 848E 97C3 CEA2 AB72 5CE4 45F9 6A2D 3C36 FB1B Gwenole Beauchesne 2E63 B3A6 3E44 37E2 017D 2704 53C7 6266 B153 99C4 +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 diff --git a/Makefile b/Makefile index 26c9107237..2d622ecd9c 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,7 @@ vpath %.v $(SRC_PATH) vpath %.texi $(SRC_PATH) vpath %.cu $(SRC_PATH) vpath %.ptx $(SRC_PATH) +vpath %.metal $(SRC_PATH) vpath %/fate_config.sh.template $(SRC_PATH) TESTTOOLS = audiogen videogen rotozoom tiny_psnr tiny_ssim base64 audiomatch @@ -89,7 +90,8 @@ SUBDIR_VARS := CLEANFILES FFLIBS HOSTPROGS TESTPROGS TOOLS \ ARMV5TE-OBJS ARMV6-OBJS ARMV8-OBJS VFP-OBJS NEON-OBJS \ ALTIVEC-OBJS VSX-OBJS MMX-OBJS X86ASM-OBJS \ MIPSFPU-OBJS MIPSDSPR2-OBJS MIPSDSP-OBJS MSA-OBJS \ - MMI-OBJS OBJS SLIBOBJS HOSTOBJS TESTOBJS + MMI-OBJS LSX-OBJS LASX-OBJS OBJS SLIBOBJS SHLIBOBJS \ + STLIBOBJS HOSTOBJS TESTOBJS define RESET $(1) := diff --git a/configure b/configure index 92610c7edc..1413122d87 100755 --- a/configure +++ b/configure @@ -262,6 +262,7 @@ External library support: --enable-librsvg enable SVG rasterization via librsvg [no] --enable-librubberband enable rubberband needed for rubberband filter [no] --enable-librtmp enable RTMP[E] support via librtmp [no] + --enable-libshaderc enable GLSL->SPIRV compilation via libshaderc [no] --enable-libshine enable fixed-point MP3 encoding via libshine [no] --enable-libsmbclient enable Samba protocol via libsmbclient [no] --enable-libsnappy enable Snappy compression, needed for hap encoding [no] @@ -297,7 +298,7 @@ External library support: --enable-libxvid enable Xvid encoding via xvidcore, native MPEG-4/Xvid encoder exists [no] --enable-libxml2 enable XML parsing using the C library libxml2, needed - for dash demuxing support [no] + for dash and imf demuxing support [no] --enable-libzimg enable z.lib, needed for zscale filter [no] --enable-libzmq enable message passing via libzmq [no] --enable-libzvbi enable teletext support via libzvbi [no] @@ -308,6 +309,7 @@ External library support: if openssl, gnutls or libtls is not used [no] --enable-mediacodec enable Android MediaCodec support [no] --enable-mediafoundation enable encoding via MediaFoundation [auto] + --disable-metal disable Apple Metal framework [autodetect] --enable-libmysofa enable libmysofa, needed for sofalizer filter [no] --enable-openal enable OpenAL 1.1 capture support [no] --enable-opencl enable OpenCL processing [no] @@ -322,7 +324,7 @@ External library support: --disable-securetransport disable Secure Transport, needed for TLS support on OSX if openssl and gnutls are not used [autodetect] --enable-vapoursynth enable VapourSynth demuxer [no] - --enable-vulkan enable Vulkan code [no] + --disable-vulkan disable Vulkan code [autodetect] --disable-xlib disable xlib [autodetect] --disable-zlib disable zlib [autodetect] @@ -381,6 +383,8 @@ Toolchain options: --dep-cc=DEPCC use dependency generator DEPCC [$cc_default] --nvcc=NVCC use Nvidia CUDA compiler NVCC or clang [$nvcc_default] --ld=LD use linker LD [$ld_default] + --metalcc=METALCC use metal compiler METALCC [$metalcc_default] + --metallib=METALLIB use metal linker METALLIB [$metallib_default] --pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [$pkg_config_default] --pkg-config-flags=FLAGS pass additional flags to pkgconf [] --ranlib=RANLIB use ranlib RANLIB [$ranlib_default] @@ -451,7 +455,9 @@ Optimization options (experts only): --disable-mipsdspr2 disable MIPS DSP ASE R2 optimizations --disable-msa disable MSA optimizations --disable-mipsfpu disable floating point MIPS optimizations - --disable-mmi disable Loongson SIMD optimizations + --disable-mmi disable Loongson MMI optimizations + --disable-lsx disable Loongson LSX optimizations + --disable-lasx disable Loongson LASX optimizations --disable-fast-unaligned consider unaligned accesses slow Developer options (useful when working on FFmpeg itself): @@ -1466,10 +1472,12 @@ test_pkg_config_cpp(){ test_cmd $pkg_config --exists --print-errors $pkg_version || return pkg_cflags=$($pkg_config --cflags $pkg_config_flags $pkg) pkg_incdir=$($pkg_config --variable=includedir $pkg_config_flags $pkg) + pkg_incflags=$($pkg_config --cflags-only-I $pkg_config_flags $pkg) test_cpp_condition "$pkg_incdir/$headers" "$cond" "$@" && enable $name && set_sanitized "${name}_cflags" $pkg_cflags && - set_sanitized "${name}_incdir" $pkg_incdir + set_sanitized "${name}_incdir" $pkg_incdir && + set_sanitized "${name}_incflags" $pkg_incflags } check_pkg_config(){ @@ -1486,6 +1494,13 @@ check_pkg_config_cpp(){ eval add_cflags \$${name}_cflags } +check_pkg_config_header_only(){ + log check_pkg_config_cpp "$@" + name="$1" + test_pkg_config_cpp "$@" && + eval add_cflags \$${name}_incflags +} + test_exec(){ test_ld "cc" "$@" && { enabled cross_compile || $TMPE >> $logfile 2>&1; } } @@ -1743,6 +1758,7 @@ EXTERNAL_AUTODETECT_LIBRARY_LIST=" libxcb_xfixes lzma mediafoundation + metal schannel sdl2 securetransport @@ -1827,12 +1843,14 @@ EXTERNAL_LIBRARY_LIST=" libopenmpt libopenvino libopus + libplacebo libpulse librabbitmq librav1e librist librsvg librtmp + libshaderc libshine libsmbclient libsnappy @@ -1879,6 +1897,7 @@ HWACCEL_AUTODETECT_LIBRARY_LIST=" vaapi vdpau videotoolbox + vulkan v4l2_m2m xvmc " @@ -1901,7 +1920,6 @@ HWACCEL_LIBRARY_LIST=" mmal omx opencl - vulkan " DOCUMENT_LIST=" @@ -2020,12 +2038,16 @@ ARCH_LIST=" avr32_uc bfin ia64 + loongarch + loongarch32 + loongarch64 m68k mips mips64 parisc ppc ppc64 + riscv s390 sh4 sparc @@ -2065,6 +2087,8 @@ ARCH_EXT_LIST_LOONGSON=" loongson2 loongson3 mmi + lsx + lasx " ARCH_EXT_LIST_X86_SIMD=" @@ -2324,10 +2348,21 @@ TOOLCHAIN_FEATURES=" TYPES_LIST=" kCMVideoCodecType_HEVC kCMVideoCodecType_HEVCWithAlpha + kCMVideoCodecType_VP9 kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange + kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ kCVImageBufferTransferFunction_ITU_R_2100_HLG kCVImageBufferTransferFunction_Linear + kCVImageBufferYCbCrMatrix_ITU_R_2020 + kCVImageBufferColorPrimaries_ITU_R_2020 + kCVImageBufferTransferFunction_ITU_R_2020 + kCVImageBufferTransferFunction_SMPTE_ST_428_1 socklen_t struct_addrinfo struct_group_source_req @@ -2399,6 +2434,7 @@ CONFIG_EXTRA=" cbs_vp9 dirac_parse dnn + dovi_rpu dvprofile exif faandct @@ -2440,7 +2476,9 @@ CONFIG_EXTRA=" mpegaudio mpegaudiodsp mpegaudioheader + mpeg4audio mpegvideo + mpegvideodec mpegvideoenc mss34dsp pixblockdsp @@ -2533,6 +2571,8 @@ CMDLINE_SET=" ln_s logfile malloc_prefix + metalcc + metallib nm optflags nvcc @@ -2590,6 +2630,10 @@ power8_deps="vsx" loongson2_deps="mips" loongson3_deps="mips" +mmi_deps_any="loongson2 loongson3" +lsx_deps="loongarch" +lasx_deps="lsx" + mips32r2_deps="mips" mips32r5_deps="mips" mips32r6_deps="mips" @@ -2598,7 +2642,6 @@ mips64r6_deps="mips" mipsfpu_deps="mips" mipsdsp_deps="mips" mipsdspr2_deps="mips" -mmi_deps_any="loongson2 loongson3" msa_deps="mipsfpu" cpunop_deps="i686" @@ -2636,7 +2679,7 @@ for ext in $(filter_out mmx $ARCH_EXT_LIST_X86_SIMD); do done aligned_stack_if_any="aarch64 ppc x86" -fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 sparc64 x86_64" +fast_64bit_if_any="aarch64 alpha ia64 mips64 parisc64 ppc64 riscv64 sparc64 x86_64" fast_clz_if_any="aarch64 alpha avr32 mips ppc x86" fast_unaligned_if_any="aarch64 ppc x86" simd_align_16_if_any="altivec neon sse" @@ -2666,6 +2709,7 @@ cbs_mpeg2_select="cbs" cbs_vp9_select="cbs" dct_select="rdft" dirac_parse_select="golomb" +dovi_rpu_select="golomb" dnn_suggest="libtensorflow libopenvino" dnn_deps="avformat swscale" error_resilience_select="me_cmp" @@ -2677,20 +2721,22 @@ h264dsp_select="startcode" hevcparse_select="atsc_a53 golomb" frame_thread_encoder_deps="encoders threads" intrax8_select="blockdsp idctdsp" +iso_media_select="mpeg4audio" mdct_select="fft" mdct15_select="fft" 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" # decoders / encoders -aac_decoder_select="adts_header mdct15 mdct sinewin" -aac_fixed_decoder_select="adts_header mdct" +aac_decoder_select="adts_header mdct15 mdct mpeg4audio sinewin" +aac_fixed_decoder_select="adts_header mdct mpeg4audio" aac_encoder_select="audio_frame_queue iirfilter lpc mdct sinewin" aac_latm_decoder_select="aac_decoder aac_latm_parser" ac3_decoder_select="ac3_parser ac3dsp bswapdsp fmtconvert mdct" @@ -2702,7 +2748,7 @@ adpcm_g722_decoder_select="g722dsp" adpcm_g722_encoder_select="g722dsp" aic_decoder_select="golomb idctdsp" alac_encoder_select="lpc" -als_decoder_select="bswapdsp" +als_decoder_select="bswapdsp mpeg4audio" amrnb_decoder_select="lsp" amrwb_decoder_select="lsp" amv_decoder_select="sp5x_decoder exif" @@ -2772,9 +2818,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" @@ -2784,7 +2830,7 @@ h264_decoder_suggest="error_resilience" hap_decoder_select="snappy texturedsp" hap_encoder_deps="libsnappy" hap_encoder_select="texturedspenc" -hevc_decoder_select="atsc_a53 bswapdsp cabac golomb hevcparse videodsp" +hevc_decoder_select="atsc_a53 bswapdsp cabac dovi_rpu golomb hevcparse videodsp" huffyuv_decoder_select="bswapdsp huffyuvdsp llviddsp" huffyuv_encoder_select="bswapdsp huffman huffyuvencdsp llvidencdsp" hymt_decoder_select="huffyuv_decoder" @@ -2796,7 +2842,7 @@ 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" @@ -2822,14 +2868,14 @@ mp3_decoder_select="mpegaudio" mp3adu_decoder_select="mpegaudio" mp3adufloat_decoder_select="mpegaudio" mp3float_decoder_select="mpegaudio" -mp3on4_decoder_select="mpegaudio" -mp3on4float_decoder_select="mpegaudio" +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" @@ -2840,7 +2886,7 @@ 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" @@ -2873,8 +2919,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" @@ -2910,7 +2956,7 @@ 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" +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" @@ -3041,6 +3087,8 @@ mpeg4_vdpau_hwaccel_deps="vdpau" mpeg4_vdpau_hwaccel_select="mpeg4_decoder" mpeg4_videotoolbox_hwaccel_deps="videotoolbox" mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder" +prores_videotoolbox_hwaccel_deps="videotoolbox" +prores_videotoolbox_hwaccel_select="prores_decoder" vc1_d3d11va_hwaccel_deps="d3d11va" vc1_d3d11va_hwaccel_select="vc1_decoder" vc1_d3d11va2_hwaccel_deps="d3d11va" @@ -3069,6 +3117,8 @@ vp9_vaapi_hwaccel_deps="vaapi VADecPictureParameterBufferVP9_bit_depth" vp9_vaapi_hwaccel_select="vp9_decoder" vp9_vdpau_hwaccel_deps="vdpau VdpPictureInfoVP9" vp9_vdpau_hwaccel_select="vp9_decoder" +vp9_videotoolbox_hwaccel_deps="videotoolbox" +vp9_videotoolbox_hwaccel_select="vp9_decoder" wmv3_d3d11va_hwaccel_select="vc1_d3d11va_hwaccel" wmv3_d3d11va2_hwaccel_select="vc1_d3d11va2_hwaccel" wmv3_dxva2_hwaccel_select="vc1_dxva2_hwaccel" @@ -3090,6 +3140,7 @@ v4l2_m2m_deps="linux_videodev2_h sem_timedwait" hwupload_cuda_filter_deps="ffnvcodec" scale_npp_filter_deps="ffnvcodec libnpp" +scale2ref_npp_filter_deps="ffnvcodec libnpp" scale_cuda_filter_deps="ffnvcodec" scale_cuda_filter_deps_any="cuda_nvcc cuda_llvm" thumbnail_cuda_filter_deps="ffnvcodec" @@ -3195,17 +3246,17 @@ wmv3_crystalhd_decoder_select="crystalhd" av1_qsv_decoder_select="qsvdec" # parsers -aac_parser_select="adts_header" +aac_parser_select="adts_header mpeg4audio" av1_parser_select="cbs_av1" 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 -aac_adtstoasc_bsf_select="adts_header" +aac_adtstoasc_bsf_select="adts_header mpeg4audio" av1_frame_merge_bsf_select="cbs_av1" av1_frame_split_bsf_select="cbs_av1" av1_metadata_bsf_select="cbs_av1" @@ -3261,6 +3312,8 @@ h264_videotoolbox_encoder_deps="pthreads" h264_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" hevc_videotoolbox_encoder_deps="pthreads" hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder" +prores_videotoolbox_encoder_deps="pthreads" +prores_videotoolbox_encoder_select="videotoolbox_encoder" libaom_av1_decoder_deps="libaom" libaom_av1_encoder_deps="libaom" libaom_av1_encoder_select="extract_extradata_bsf" @@ -3302,7 +3355,7 @@ librav1e_encoder_deps="librav1e" librav1e_encoder_select="extract_extradata_bsf" librsvg_decoder_deps="librsvg" libshine_encoder_deps="libshine" -libshine_encoder_select="audio_frame_queue" +libshine_encoder_select="audio_frame_queue mpegaudioheader" libspeex_decoder_deps="libspeex" libspeex_encoder_deps="libspeex" libspeex_encoder_select="audio_frame_queue" @@ -3338,7 +3391,9 @@ videotoolbox_encoder_deps="videotoolbox VTCompressionSessionPrepareToEncodeFrame # demuxers / muxers ac3_demuxer_select="ac3_parser" act_demuxer_select="riffdec" +adts_muxer_select="mpeg4audio" aiff_muxer_select="iso_media" +amv_muxer_select="riffenc" asf_demuxer_select="riffdec" asf_o_demuxer_select="riffdec" asf_muxer_select="riffenc" @@ -3363,18 +3418,21 @@ flac_demuxer_select="flac_parser" flv_muxer_select="aac_adtstoasc_bsf" gxf_muxer_select="pcm_rechunk_bsf" hds_muxer_select="flv_muxer" +hls_demuxer_select="adts_header ac3_parser" hls_muxer_select="mpegts_muxer" hls_muxer_suggest="gcrypt openssl" image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" +imf_demuxer_deps="libxml2" +imf_demuxer_select="mxf_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" -latm_muxer_select="aac_adtstoasc_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="riffenc vp9_superframe_bsf aac_adtstoasc_bsf" +matroska_muxer_select="mpeg4audio riffenc vp9_superframe_bsf aac_adtstoasc_bsf" mlp_demuxer_select="mlp_parser" mmf_muxer_select="riffenc" mov_demuxer_select="iso_media riffdec" @@ -3386,7 +3444,7 @@ mp4_muxer_select="mov_muxer" mpegts_demuxer_select="iso_media" mpegts_muxer_select="ac3_parser adts_muxer latm_muxer h264_mp4toannexb_bsf hevc_mp4toannexb_bsf" mpegtsraw_demuxer_select="mpegts_demuxer" -mxf_muxer_select="golomb pcm_rechunk_bsf" +mxf_muxer_select="pcm_rechunk_bsf" mxf_d10_muxer_select="mxf_muxer" mxf_opatom_muxer_select="mxf_muxer" nut_muxer_select="riffenc" @@ -3399,9 +3457,8 @@ ogv_muxer_select="ogg_muxer" opus_muxer_select="ogg_muxer" psp_muxer_select="mov_muxer" rtp_demuxer_select="sdp_demuxer" -rtp_muxer_select="golomb jpegtables" rtp_mpegts_muxer_select="mpegts_muxer rtp_muxer" -rtpdec_select="asf_demuxer jpegtables mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" +rtpdec_select="asf_demuxer mov_demuxer mpegts_demuxer rm_demuxer rtp_protocol srtp" rtsp_demuxer_select="http_protocol rtpdec" rtsp_muxer_select="rtp_muxer http_protocol rtp_protocol rtpenc_chain" sap_demuxer_select="sdp_demuxer" @@ -3422,7 +3479,6 @@ w64_muxer_select="wav_muxer" wav_demuxer_select="riffdec" wav_muxer_select="riffenc" webm_chunk_muxer_select="webm_muxer" -webm_muxer_select="riffenc" webm_dash_manifest_demuxer_select="matroska_demuxer" wtv_demuxer_select="mpegts_demuxer riffdec" wtv_muxer_select="mpegts_muxer riffenc" @@ -3444,6 +3500,7 @@ caca_outdev_deps="libcaca" decklink_deps_any="libdl LoadLibrary" decklink_indev_deps="decklink threads" decklink_indev_extralibs="-lstdc++" +decklink_indev_suggest="libzvbi" decklink_outdev_deps="decklink threads" decklink_outdev_suggest="libklvanc" decklink_outdev_extralibs="-lstdc++" @@ -3557,15 +3614,16 @@ ass_filter_deps="libass" atempo_filter_deps="avcodec" atempo_filter_select="rdft" avgblur_opencl_filter_deps="opencl" -avgblur_vulkan_filter_deps="vulkan_lib libglslang" +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" boxblur_opencl_filter_deps="opencl gpl" bs2b_filter_deps="libbs2b" -chromaber_vulkan_filter_deps="vulkan_lib libglslang" +chromaber_vulkan_filter_deps="vulkan spirv_compiler" colorkey_opencl_filter_deps="opencl" colormatrix_filter_deps="gpl" convolution_opencl_filter_deps="opencl" @@ -3598,6 +3656,7 @@ fftdnoiz_filter_select="fft" find_rect_filter_deps="avcodec avformat gpl" firequalizer_filter_deps="avcodec" firequalizer_filter_select="rdft" +flip_vulkan_filter_deps="vulkan spirv_compiler" flite_filter_deps="libflite" framerate_filter_select="scene_sad" freezedetect_filter_select="scene_sad" @@ -3605,12 +3664,15 @@ frei0r_deps_any="libdl LoadLibrary" frei0r_filter_deps="frei0r" frei0r_src_filter_deps="frei0r" fspp_filter_deps="gpl" +gblur_vulkan_filter_deps="vulkan spirv_compiler" +hflip_vulkan_filter_deps="vulkan spirv_compiler" histeq_filter_deps="gpl" hqdn3d_filter_deps="gpl" interlace_filter_deps="gpl" kerndeint_filter_deps="gpl" ladspa_filter_deps="ladspa libdl" lensfun_filter_deps="liblensfun version3" +libplacebo_filter_deps="libplacebo vulkan" lv2_filter_deps="lv2" mcdeint_filter_deps="avcodec gpl" metadata_filter_deps="avformat" @@ -3628,7 +3690,7 @@ openclsrc_filter_deps="opencl" overlay_opencl_filter_deps="opencl" overlay_qsv_filter_deps="libmfx" overlay_qsv_filter_select="qsvvpp" -overlay_vulkan_filter_deps="vulkan_lib libglslang" +overlay_vulkan_filter_deps="vulkan spirv_compiler" owdenoise_filter_deps="gpl" pad_opencl_filter_deps="opencl" pan_filter_deps="swresample" @@ -3681,9 +3743,11 @@ tonemap_vaapi_filter_deps="vaapi VAProcFilterParameterBufferHDRToneMapping" tonemap_opencl_filter_deps="opencl const_nan" transpose_opencl_filter_deps="opencl" transpose_vaapi_filter_deps="vaapi VAProcPipelineCaps_rotation_flags" +transpose_vulkan_filter_deps="vulkan spirv_compiler" unsharp_opencl_filter_deps="opencl" uspp_filter_deps="gpl avcodec" vaguedenoiser_filter_deps="gpl" +vflip_vulkan_filter_deps="vulkan spirv_compiler" vidstabdetect_filter_deps="libvidstab" vidstabtransform_filter_deps="libvidstab" libvmaf_filter_deps="libvmaf pthreads" @@ -3691,12 +3755,13 @@ zmq_filter_deps="libzmq" zoompan_filter_deps="swscale" zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" -scale_vulkan_filter_deps="vulkan_lib libglslang" +scale_vulkan_filter_deps="vulkan spirv_compiler" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" xfade_opencl_filter_deps="opencl" yadif_cuda_filter_deps="ffnvcodec" yadif_cuda_filter_deps_any="cuda_nvcc cuda_llvm" +yadif_videotoolbox_filter_deps="metal corevideo videotoolbox" # examples avio_list_dir_deps="avformat avutil" @@ -3789,6 +3854,8 @@ host_cc_default="gcc" doxygen_default="doxygen" install="install" ln_s_default="ln -s -f" +metalcc_default="xcrun -sdk macosx metal" +metallib_default="xcrun -sdk macosx metallib" nm_default="nm -g" pkg_config_default=pkg-config ranlib_default="ranlib" @@ -4389,7 +4456,7 @@ if enabled cuda_nvcc; then fi set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \ - target_exec x86asmexe + target_exec x86asmexe metalcc metallib enabled cross_compile || host_cc_default=$cc set_default host_cc @@ -4925,6 +4992,9 @@ case "$arch" in arm*|iPad*|iPhone*) arch="arm" ;; + loongarch*) + arch="loongarch" + ;; mips*|IP*) case "$arch" in *el) @@ -4944,6 +5014,9 @@ case "$arch" in "Power Macintosh"|ppc*|powerpc*) arch="ppc" ;; + riscv*) + arch="riscv" + ;; s390|s390x) arch="s390" ;; @@ -5069,6 +5142,18 @@ elif enabled bfin; then cpuflags="-mcpu=$cpu" +elif enabled loongarch; then + + enable local_aligned + enable simd_align_32 + enable fast_64bit + enable fast_clz + enable fast_unaligned + case $cpu in + la464) + cpuflags="-march=$cpu" + ;; + esac elif enabled mips; then if [ "$cpu" != "generic" ]; then @@ -5325,6 +5410,11 @@ case "$arch" in aarch64|alpha|ia64) enabled shared && enable_weak pic ;; + loongarch) + check_64bit loongarch32 loongarch64 + enabled loongarch64 && disable loongarch32 + enabled shared && enable_weak pic + ;; mips) check_64bit mips mips64 '_MIPS_SIM > 1' enabled shared && enable_weak pic @@ -5337,6 +5427,10 @@ case "$arch" in check_64bit ppc ppc64 enabled shared && enable_weak pic ;; + riscv) + check_64bit riscv32 riscv64 + enabled shared && enable_weak pic + ;; s390) check_64bit s390 s390x enabled shared && enable_weak pic @@ -6068,6 +6162,9 @@ EOF ;; esac +elif enabled loongarch; then + enabled lsx && check_inline_asm lsx '"vadd.b $vr0, $vr1, $vr2"' '-mlsx' && append LSXFLAGS '-mlsx' + enabled lasx && check_inline_asm lasx '"xvadd.b $xr0, $xr1, $xr2"' '-mlasx' && append LASXFLAGS '-mlasx' fi check_cc intrinsics_neon arm_neon.h "int16x8_t test = vdupq_n_s16(0)" @@ -6244,6 +6341,7 @@ enabled appkit && check_apple_framework AppKit enabled audiotoolbox && check_apple_framework AudioToolbox enabled avfoundation && check_apple_framework AVFoundation enabled coreimage && check_apple_framework CoreImage +enabled metal && check_apple_framework Metal enabled videotoolbox && check_apple_framework VideoToolbox check_apple_framework CoreFoundation @@ -6260,12 +6358,25 @@ enabled videotoolbox && { check_lib coreservices CoreServices/CoreServices.h UTGetOSTypeFromString "-framework CoreServices" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia" check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVCWithAlpha "-framework CoreMedia" + check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_VP9 "-framework CoreMedia" check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange "-framework CoreVideo" + check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2100_HLG "-framework CoreVideo" check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_Linear "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferYCbCrMatrix_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferColorPrimaries_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_ITU_R_2020 "-framework CoreVideo" + check_func_headers CoreVideo/CVImageBuffer.h kCVImageBufferTransferFunction_SMPTE_ST_428_1 "-framework CoreVideo" } +enabled metal && test_cmd $metalcc -v || disable metal + check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss check_type "windows.h dxva.h" "DXVA_PicParams_AV1" -DWINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP -D_CRT_BUILD_DESKTOP_APP=0 @@ -6306,6 +6417,10 @@ if ! disabled ffnvcodec; then check_pkg_config ffnvcodec "ffnvcodec >= 8.1.24.11 ffnvcodec < 8.2" "$ffnv_hdr_list" "" fi +if enabled_all libglslang libshaderc; then + die "ERROR: libshaderc and libglslang are mutually exclusive, if in doubt, disable libglslang" +fi + check_cpp_condition winrt windows.h "!WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)" if ! disabled w32threads && ! enabled pthreads; then @@ -6401,7 +6516,7 @@ enabled libaribb24 && { check_pkg_config libaribb24 "aribb24 > 1.0.3" "ar die "ERROR: libaribb24 requires version higher than 1.0.3 or --enable-gpl."; } enabled lv2 && require_pkg_config lv2 lilv-0 "lilv/lilv.h" lilv_world_new enabled libiec61883 && require libiec61883 libiec61883/iec61883.h iec61883_cmp_connect -lraw1394 -lavc1394 -lrom1394 -liec61883 -enabled libass && require_pkg_config libass libass ass/ass.h ass_library_init +enabled libass && require_pkg_config libass "libass >= 0.11.0" ass/ass.h ass_library_init enabled libbluray && require_pkg_config libbluray libbluray libbluray/bluray.h bd_open enabled libbs2b && require_pkg_config libbs2b libbs2b bs2b.h bs2b_open enabled libcelt && require libcelt celt/celt.h celt_decode -lcelt0 && @@ -6422,7 +6537,12 @@ enabled fontconfig && enable libfontconfig enabled libfontconfig && require_pkg_config libfontconfig fontconfig "fontconfig/fontconfig.h" FcInit enabled libfreetype && require_pkg_config libfreetype freetype2 "ft2build.h FT_FREETYPE_H" FT_Init_FreeType enabled libfribidi && require_pkg_config libfribidi fribidi fribidi.h fribidi_version_info -enabled libglslang && require_cpp libglslang glslang/SPIRV/GlslangToSpv.h "glslang::TIntermediate*" -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ +enabled libglslang && { check_lib spirv_compiler glslang/Include/glslang_c_interface.h glslang_initialize_process \ + -lglslang -lMachineIndependent -lOSDependent -lHLSL -lOGLCompiler -lGenericCodeGen \ + -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm || + require spirv_compiler glslang/Include/glslang_c_interface.h glslang_initialize_process \ + -lglslang -lOSDependent -lHLSL -lOGLCompiler \ + -lSPVRemapper -lSPIRV -lSPIRV-Tools-opt -lSPIRV-Tools -lpthread -lstdc++ -lm; } enabled libgme && { check_pkg_config libgme libgme gme/gme.h gme_new_emu || require libgme gme/gme.h gme_new_emu -lgme -lstdc++; } enabled libgsm && { for gsm_hdr in "gsm.h" "gsm/gsm.h"; do @@ -6470,6 +6590,7 @@ enabled libopus && { require_pkg_config libopus opus opus_multistream.h opus_multistream_surround_encoder_create } } +enabled libplacebo && require_pkg_config libplacebo "libplacebo >= 4.192.0" libplacebo/vulkan.h pl_vulkan_create 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 @@ -6477,6 +6598,7 @@ enabled librist && require_pkg_config librist "librist >= 0.2" librist 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++" +enabled libshaderc && require_pkg_config spirv_compiler "shaderc >= 2019.1" shaderc/shaderc.h shaderc_compiler_initialize enabled libshine && require_pkg_config libshine shine shine/layer3.h shine_encode_buffer enabled libsmbclient && { check_pkg_config libsmbclient smbclient libsmbclient.h smbc_init || require libsmbclient libsmbclient.h smbc_init -lsmbclient; } @@ -6709,7 +6831,8 @@ enabled alsa && { check_pkg_config alsa alsa "alsa/asoundlib.h" snd_pcm_htimesta enabled libjack && require_pkg_config libjack jack jack/jack.h jack_port_get_latency_range -enabled sndio && check_lib sndio sndio.h sio_open -lsndio +enabled sndio && { check_pkg_config sndio sndio "sndio.h" sio_open || + check_lib sndio sndio.h sio_open -lsndio; } if enabled libcdio; then check_pkg_config libcdio libcdio_paranoia "cdio/cdda.h cdio/paranoia.h" cdio_cddap_open || @@ -6806,10 +6929,8 @@ enabled vdpau && enabled crystalhd && check_lib crystalhd "stdint.h libcrystalhd/libcrystalhd_if.h" DtsCrystalHDVersion -lcrystalhd if enabled vulkan; then - require_pkg_config_cpp vulkan "vulkan >= 1.1.97" "vulkan/vulkan.h" "defined VK_VERSION_1_1" || - require_cpp_condition vulkan "vulkan/vulkan.h" "defined VK_VERSION_1_1" - # vulkan_lib should be removed once glslang filters are updated - check_pkg_config vulkan_lib "vulkan >= 1.1.97" "vulkan/vulkan.h" vkCreateInstance + check_pkg_config_header_only vulkan "vulkan >= 1.2.189" "vulkan/vulkan.h" "defined VK_VERSION_1_2" || + check_cpp_condition vulkan "vulkan/vulkan.h" "defined(VK_VERSION_1_3) || (defined(VK_VERSION_1_2) && VK_HEADER_VERSION >= 189)" fi if enabled x86; then @@ -6869,7 +6990,6 @@ check_cflags -Wwrite-strings check_cflags -Wtype-limits check_cflags -Wundef check_cflags -Wmissing-prototypes -check_cflags -Wno-pointer-to-int-cast check_cflags -Wstrict-prototypes check_cflags -Wempty-body @@ -7399,6 +7519,10 @@ if enabled ppc; then echo "PPC 4xx optimizations ${ppc4xx-no}" echo "dcbzl available ${dcbzl-no}" fi +if enabled loongarch; then + echo "LSX enabled ${lsx-no}" + echo "LASX enabled ${lasx-no}" +fi echo "debug symbols ${debug-no}" echo "strip symbols ${stripping-no}" echo "optimize for size ${small-no}" @@ -7521,6 +7645,8 @@ ARFLAGS=$arflags AR_O=$ar_o AR_CMD=$ar NM_CMD=$nm +METALCC=$metalcc +METALLIB=$metallib RANLIB=$ranlib STRIP=$strip STRIPTYPE=$striptype @@ -7530,7 +7656,7 @@ LN_S=$ln_s CPPFLAGS=$CPPFLAGS CFLAGS=$CFLAGS CXXFLAGS=$CXXFLAGS -OBJCFLAGS=$OBJCFLAGS +OBJCCFLAGS=$OBJCFLAGS ASFLAGS=$ASFLAGS NVCCFLAGS=$nvccflags AS_C=$AS_C @@ -7560,6 +7686,8 @@ ASMSTRIPFLAGS=$ASMSTRIPFLAGS X86ASMFLAGS=$X86ASMFLAGS MSAFLAGS=$MSAFLAGS MMIFLAGS=$MMIFLAGS +LSXFLAGS=$LSXFLAGS +LASXFLAGS=$LASXFLAGS BUILDSUF=$build_suffix PROGSSUF=$progs_suffix FULLNAME=$FULLNAME @@ -7578,6 +7706,8 @@ ASDEP_FLAGS=$ASDEP_FLAGS X86ASMDEP=$X86ASMDEP X86ASMDEP_FLAGS=$X86ASMDEP_FLAGS CC_DEPFLAGS=$CC_DEPFLAGS +CXX_DEPFLAGS=$CXX_DEPFLAGS +OBJCC_DEPFLAGS=$OBJC_DEPFLAGS AS_DEPFLAGS=$AS_DEPFLAGS X86ASM_DEPFLAGS=$X86ASM_DEPFLAGS HOSTCC=$host_cc @@ -7633,7 +7763,7 @@ cat > $TMPH <} as metadata keys named "id" and "variant_bitrate" respectively. +@section imf + +Interoperable Master Format demuxer. + +This demuxer presents audio and video streams found in an IMF Composition. + @section flv, live_flv, kux Adobe Flash Video Format demuxer. @@ -691,7 +704,7 @@ Don't use mfra box to set timestamps @item use_tfdt For fragmented input, set fragment's starting timestamp to @code{baseMediaDecodeTime} from the @code{tfdt} box. -Default is disabled, which will preferentially use the @code{earliest_presentation_time} from the @code{sidx} box. +Default is enabled, which will prefer to use the @code{tfdt} box to set DTS. Disable to use the @code{earliest_presentation_time} from the @code{sidx} box. In either case, the timestamp from the @code{mfra} box will be used if it's available and @code{use_mfra_for} is set to pts or dts. @@ -713,6 +726,15 @@ specify. @item decryption_key 16-byte key, in hex, to decrypt files encrypted using ISO Common Encryption (CENC/AES-128 CTR; ISO/IEC 23001-7). + +@item max_stts_delta +Very high sample deltas written in a trak's stts box may occasionally be intended but usually they are written in +error or used to store a negative value for dts correction when treated as signed 32-bit integers. This option lets +the user set an upper limit, beyond which the delta is clamped to 1. Values greater than the limit if negative when +cast to int32 are used to adjust onward dts. + +Unit is the track time scale. Range is 0 to UINT_MAX. Default is @code{UINT_MAX - 48000*10} which allows upto +a 10 second dts correction for 48 kHz audio streams while accommodating 99.9% of @code{uint32} range. @end table @subsection Audible AAX diff --git a/doc/developer.texi b/doc/developer.texi index b33cab0fc7..addee0d826 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -494,6 +494,22 @@ patch is inline or attached per mail. You can check @url{https://patchwork.ffmpeg.org}, if your patch does not show up, its mime type likely was wrong. +@subheading Sending patches from email clients +Using @code{git send-email} might not be desirable for everyone. The +following trick allows to send patches via email clients in a safe +way. It has been tested with Outlook and Thunderbird (with X-Unsent +extension) and might work with other applications. + +Create your patch like this: + +@verbatim +git format-patch -s -o "outputfolder" --add-header "X-Unsent: 1" --suffix .eml --to ffmpeg-devel@ffmpeg.org -1 1a2b3c4d +@end verbatim + +Now you'll just need to open the eml file with the email application +and execute 'Send'. + +@subheading Reviews Your patch will be reviewed on the mailing list. You will likely be asked to make some changes and are expected to send in an improved version that incorporates the requests from the review. This process may go through diff --git a/doc/encoders.texi b/doc/encoders.texi index 8a7589c245..7cc8be1209 100644 --- a/doc/encoders.texi +++ b/doc/encoders.texi @@ -2660,6 +2660,9 @@ ffmpeg -i foo.mpg -c:v libx264 -x264opts keyint=123:min-keyint=20 -an out.mkv Import closed captions (which must be ATSC compatible format) into output. Only the mpeg2 and h264 decoders provide these. Default is 1 (on). +@item udu_sei @var{boolean} +Import user data unregistered SEI if available into output. Default is 0 (off). + @item x264-params (N.A.) Override the x264 configuration using a :-separated list of key=value parameters. @@ -2741,6 +2744,9 @@ Quantizer curve compression factor Normally, when forcing a I-frame type, the encoder can select any type of I-frame. This option forces it to choose an IDR-frame. +@item udu_sei @var{boolean} +Import user data unregistered SEI if available into output. Default is 0 (off). + @item x265-params Set x265 options using a list of @var{key}=@var{value} couples separated by ":". See @command{x265 --help} for a list of options. @@ -3117,12 +3123,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. @@ -3170,6 +3177,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 @@ -3206,6 +3214,251 @@ 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 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_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{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{b_strategy} +This option controls usage of B frames as reference. + +@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. + +@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{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. +@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{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} +@table @samp +@item unknown +@item main +@item main10 +@item mainsp +@item rext +@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. +@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 +@end table + @section snow @subsection Options diff --git a/doc/examples/metadata.c b/doc/examples/metadata.c index b6cfa6bd36..7c44009a24 100644 --- a/doc/examples/metadata.c +++ b/doc/examples/metadata.c @@ -34,7 +34,7 @@ int main (int argc, char **argv) { AVFormatContext *fmt_ctx = NULL; - AVDictionaryEntry *tag = NULL; + const AVDictionaryEntry *tag = NULL; int ret; if (argc != 2) { diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi index 62d9703b7a..164419cad3 100644 --- a/doc/ffmpeg.texi +++ b/doc/ffmpeg.texi @@ -560,27 +560,22 @@ ffmpeg -i INPUT -metadata:s:a:0 language=eng OUTPUT @item -disposition[:stream_specifier] @var{value} (@emph{output,per-stream}) Sets the disposition for a stream. -This option overrides the disposition copied from the input stream. It is also -possible to delete the disposition by setting it to 0. +By default, the disposition is copied from the input stream, unless the output +stream this option applies to is fed by a complex filtergraph - in that case the +disposition is unset by default. -The following dispositions are recognized: -@table @option -@item default -@item dub -@item original -@item comment -@item lyrics -@item karaoke -@item forced -@item hearing_impaired -@item visual_impaired -@item clean_effects -@item attached_pic -@item captions -@item descriptions -@item dependent -@item metadata -@end table +@var{value} is a sequence of items separated by '+' or '-'. The first item may +also be prefixed with '+' or '-', in which case this option modifies the default +value. Otherwise (the first item is not prefixed) this options overrides the +default value. A '+' prefix adds the given disposition, '-' removes it. It is +also possible to clear the disposition by setting it to 0. + +If no @code{-disposition} options were specified for an output file, ffmpeg will +automatically set the 'default' disposition on the first stream of each type, +when there are multiple streams of this type in the output file and no stream of +that type is already marked as default. + +The @code{-dispositions} option lists the known dispositions. For example, to make the second audio stream the default stream: @example @@ -1101,6 +1096,21 @@ device type: @item cuda @var{device} is the number of the CUDA device. +The following options are recognized: +@table @option +@item primary_ctx +If set to 1, uses the primary device context instead of creating a new one. +@end table + +Examples: +@table @emph +@item -init_hw_device cuda:1 +Choose the second device on the system. + +@item -init_hw_device cuda:0,primary_ctx=1 +Choose the first device and use the primary device context. +@end table + @item dxva2 @var{device} is the number of the Direct3D 9 display adapter. @@ -1610,23 +1620,25 @@ It is useful for when flow speed of output packets is important, such as live st Read input at native frame rate. This is equivalent to setting @code{-readrate 1}. @item -vsync @var{parameter} Video sync method. -For compatibility reasons old values can be specified as numbers. -Newly added values will have to be specified as strings always. + +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. @table @option -@item 0, passthrough +@item passthrough (0) Each frame is passed with its timestamp from the demuxer to the muxer. -@item 1, cfr +@item cfr (1) Frames will be duplicated and dropped to achieve exactly the requested constant frame rate. -@item 2, vfr +@item vfr (2) Frames are passed through with their timestamp or dropped so as to prevent 2 frames from having the same timestamp. @item drop As passthrough but destroys all timestamps, making the muxer generate fresh timestamps based on frame-rate. -@item -1, auto -Chooses between 1 and 2 depending on muxer capabilities. This is the +@item auto (-1) +Chooses between cfr and vfr depending on muxer capabilities. This is the default method. @end table @@ -1950,6 +1962,13 @@ filter (scale, aresample) in the graph. On by default, to explicitly disable it you need to specify @code{-noauto_conversion_filters}. +@item -bits_per_raw_sample[:@var{stream_specifier}] @var{value} (@emph{output,per-stream}) +Declare the number of bits per raw sample in the given output stream to be +@var{value}. Note that this option sets the information provided to the +encoder/muxer, it does not change the stream to conform to this value. Setting +values that do not match the stream properties may result in encoding failures +or invalid output files. + @end table @section Preset files diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd index b65e54dbef..3af621a17a 100644 --- a/doc/ffprobe.xsd +++ b/doc/ffprobe.xsd @@ -215,6 +215,7 @@ + diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 7643dd8396..d9145704d6 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -167,6 +167,9 @@ Show available sample formats. @item -layouts Show channel names and standard channel layouts. +@item -dispositions +Show stream dispositions. + @item -colors Show recognized color names. diff --git a/doc/filters.texi b/doc/filters.texi index 22e604f712..05d4b1a56e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -843,6 +843,102 @@ Compute derivative/integral of audio stream. Applying both filters one after another produces original audio. +@section adynamicequalizer + +Apply dynamic equalization to input audio stream. + +A description of the accepted options follows. + +@table @option +@item threshold +Set the detection threshold used to trigger equalization. +Threshold detection is using bandpass filter. +Default value is 0. Allowed range is from 0 to 100. + +@item dfrequency +Set the detection frequency in Hz used for bandpass filter used to trigger equalization. +Default value is 1000 Hz. Allowed range is between 2 and 1000000 Hz. + +@item dqfactor +Set the detection resonance factor for bandpass filter used to trigger equalization. +Default value is 1. Allowed range is from 0.001 to 1000. + +@item tfrequency +Set the target frequency of equalization filter. +Default value is 1000 Hz. Allowed range is between 2 and 1000000 Hz. + +@item tqfactor +Set the target resonance factor for target equalization filter. +Default value is 1. Allowed range is from 0.001 to 1000. + +@item attack +Set the amount of milliseconds the signal from detection has to rise above +the detection threshold before equalization starts. +Default is 20. Allowed range is between 1 and 2000. + +@item release +Set the amount of milliseconds the signal from detection has to fall below the +detection threshold before equalization ends. +Default is 200. Allowed range is between 1 and 2000. + +@item knee +Curve the sharp knee around the detection threshold to calculate +equalization gain more softly. +Default is 1. Allowed range is between 0 and 8. + +@item ratio +Set the ratio by which the equalization gain is raised. +Default is 1. Allowed range is between 1 and 20. + +@item makeup +Set the makeup offset in dB by which the equalization gain is raised. +Default is 0. Allowed range is between 0 and 30. + +@item range +Set the max allowed cut/boost amount in dB. Default is 0. +Allowed range is from 0 to 200. + +@item slew +Set the slew factor. Default is 1. Allowed range is from 1 to 200. + +@item mode +Set the mode of filter operation, can be one of the following: + +@table @samp +@item listen +Output only isolated bandpass signal. +@item cut +Cut frequencies above detection threshold. +@item boost +Boost frequencies bellow detection threshold. +@end table +Default mode is @samp{cut}. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + +@section adynamicsmooth + +Apply dynamic smoothing to input audio stream. + +A description of the accepted options follows. + +@table @option +@item sensitivity +Set an amount of sensitivity to frequency fluctations. Default is 2. +Allowed range is from 0 to 1e+06. + +@item basefreq +Set a base frequency for smoothing. Default value is 22050. +Allowed range is from 2 to 1e+06. +@end table + +@subsection Commands + +This filter supports the all above options as @ref{commands}. + @section aecho Apply echoing to the input audio. @@ -1885,6 +1981,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -2204,8 +2301,8 @@ Set smooth factor. Default value is @var{11}. Allowed range is from @var{1} to @ This filter supports the all above options as @ref{commands}. -@section anlms -Apply Normalized Least-Mean-Squares algorithm to the first audio stream using the second audio stream. +@section anlmf, anlms +Apply Normalized Least-Mean-(Squares|Fourth) algorithm to the first audio stream using the second audio stream. This adaptive filter is used to mimic a desired filter by finding the filter coefficients that relate to producing the least mean square of the error signal (difference between the desired, @@ -2291,12 +2388,12 @@ with @option{pad_len}. @item pad_dur Specify the duration of samples of silence to add. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} -for the accepted syntax. Used only if set to non-zero value. +for the accepted syntax. Used only if set to non-negative value. @item whole_dur Specify the minimum total duration in the output audio stream. See @ref{time duration syntax,,the Time duration section in the ffmpeg-utils(1) manual,ffmpeg-utils} -for the accepted syntax. Used only if set to non-zero value. If the value is longer than +for the accepted syntax. Used only if set to non-negative value. If the value is longer than the input audio length, silence is added to the end, until the value is reached. This option is mutually exclusive with @option{pad_dur} @end table @@ -2305,6 +2402,9 @@ If neither the @option{pad_len} nor the @option{whole_len} nor @option{pad_dur} nor @option{whole_dur} option is set, the filter will add silence to the end of the input stream indefinitely. +Note that for ffmpeg 4.4 and earlier a zero @option{pad_dur} or +@option{whole_dur} also caused the filter to add silence indefinitely. + @subsection Examples @itemize @@ -2691,6 +2791,69 @@ Set oversampling factor. This filter supports the all above options as @ref{commands}. +@section aspectralstats + +Display frequency domain statistical information about the audio channels. +Statistics are calculated and stored as metadata for each audio channel and for each audio frame. + +It accepts the following option: +@table @option +@item win_size +Set the window length in samples. Default value is 2048. +Allowed range is from 32 to 65536. + +@item win_func +Set window function. + +It accepts the following values: +@table @samp +@item rect +@item bartlett +@item hann, hanning +@item hamming +@item blackman +@item welch +@item flattop +@item bharris +@item bnuttall +@item bhann +@item sine +@item nuttall +@item lanczos +@item gauss +@item tukey +@item dolph +@item cauchy +@item parzen +@item poisson +@item bohman +@end table +Default is @code{hann}. + +@item overlap +Set window overlap. Allowed range is from @code{0} +to @code{1}. Default value is @code{0.5}. + +@end table + +A list of each metadata key follows: + +@table @option +@item mean +@item variance +@item centroid +@item spread +@item skewness +@item kurtosis +@item entropy +@item flatness +@item crest +@item flux +@item slope +@item decrease +@item rolloff +@end table + @section asr Automatic Speech Recognition @@ -2799,16 +2962,17 @@ this @code{lavfi.astats.Overall.Peak_count}. For description what each key means read below. @item reset -Set number of frame after which stats are going to be recalculated. +Set the number of frames over which cumulative stats are calculated before +being reset Default is disabled. @item measure_perchannel -Select the entries which need to be measured per channel. The metadata keys can +Select the parameters which are measured per channel. The metadata keys can be used as flags, default is @option{all} which measures everything. @option{none} disables all per channel measurement. @item measure_overall -Select the entries which need to be measured overall. The metadata keys can +Select the parameters which are measured overall. The metadata keys can be used as flags, default is @option{all} which measures everything. @option{none} disables all overall measurement. @@ -3246,6 +3410,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3333,6 +3498,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3430,6 +3596,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -3512,6 +3679,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -4262,6 +4430,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -4763,6 +4932,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -5113,6 +5283,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -6337,6 +6508,7 @@ Set transform type of IIR filter. @item dii @item tdii @item latt +@item svf @end table @item precision, r @@ -8048,7 +8220,7 @@ Set threshold for averaging chrominance values. Sum of absolute difference of Y, U and V pixel components of current pixel and neighbour pixels lower than this threshold will be used in averaging. Luma component is left unchanged and is copied to output. -Default value is 30. Allowed range is from 1 to 5000. +Default value is 30. Allowed range is from 1 to 200. @item sizew Set horizontal radius of rectangle used for averaging. @@ -8072,19 +8244,19 @@ Mostly useful to speed-up filtering. Set Y threshold for averaging chrominance values. Set finer control for max allowed difference between Y components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item threu Set U threshold for averaging chrominance values. Set finer control for max allowed difference between U components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item threv Set V threshold for averaging chrominance values. Set finer control for max allowed difference between V components of current pixel and neigbour pixels. -Default value is 5000. Allowed range is from 1 to 5000. +Default value is 200. Allowed range is from 1 to 200. @item distance Set distance type used in calculations. @@ -8493,25 +8665,31 @@ This filter supports the all above options as @ref{commands}. @section colorkey RGB colorspace color keying. +This filter operates on 8-bit RGB format frames by setting the alpha component of each pixel +which falls within the similarity radius of the key color to 0. The alpha value for pixels outside +the similarity radius depends on the value of the blend option. The filter accepts the following options: @table @option @item color -The color which will be replaced with transparency. +Set the color for which alpha will be set to 0 (full transparency). +See @ref{color syntax,,"Color" section in the ffmpeg-utils manual,ffmpeg-utils}. +Default is @code{black}. @item similarity -Similarity percentage with the key color. - -0.01 matches only the exact key color, while 1.0 matches everything. +Set the radius from the key color within which other colors also have full transparency. +The computed distance is related to the unit fractional distance in 3D space between the RGB values +of the key color and the pixel's color. Range is 0.01 to 1.0. 0.01 matches within a very small radius +around the exact key color, while 1.0 matches everything. +Default is @code{0.01}. @item blend -Blend percentage. - -0.0 makes pixels either fully transparent, or not transparent at all. - -Higher values result in semi-transparent pixels, with a higher transparency -the more similar the pixels color is to the key color. +Set how the alpha value for pixels that fall outside the similarity radius is computed. +0.0 makes pixels either fully transparent or fully opaque. +Higher values result in semi-transparent pixels, with greater transparency +the more similar the pixel color is to the key color. +Range is 0.0 to 1.0. Default is @code{0.0}. @end table @subsection Examples @@ -11711,6 +11889,18 @@ Allowed range is from 1 to 15. 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. + +@item mcost +Specify the middle cost for edge matching. Default value is 0.5. +Allowed range is from 0 to 1. + +@item dcost +Specify the distance cost for edge matching. Default value is 0.5. +Allowed range is from 0 to 1. + @item interp Specify the interpolation used. Default is 4-point interpolation. It accepts one of the following values: @@ -13515,6 +13705,9 @@ It accepts the following values: @item coloronblack @item coloronwhite @item colorongray +@item blackoncolor +@item whiteoncolor +@item grayoncolor @end table Default is @code{whiteonblack}. @end table @@ -13732,15 +13925,15 @@ The filter accepts the following options: @table @option @item hue -Set the hue value which will be used if color difference calculation. +Set the hue value which will be used in color difference calculation. Allowed range is from -360 to 360. Default value is 0. @item sat -Set the saturation value which will be used if color difference calculation. +Set the saturation value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item val -Set the value which will be used if color difference calculation. +Set the value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item similarity @@ -13770,15 +13963,15 @@ The filter accepts the following options: @table @option @item hue -Set the hue value which will be used if color difference calculation. +Set the hue value which will be used in color difference calculation. Allowed range is from -360 to 360. Default value is 0. @item sat -Set the saturation value which will be used if color difference calculation. +Set the saturation value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item val -Set the value which will be used if color difference calculation. +Set the value which will be used in color difference calculation. Allowed range is from -1 to 1. Default value is 0. @item similarity @@ -13905,6 +14098,62 @@ If the specified expression is not valid, it is kept at its current value. @end table +@section huesaturation +Apply hue-saturation-intensity adjustments to input video stream. + +This filter operates in RGB colorspace. + +This filter accepts the following options: + +@table @option +@item hue +Set the hue shift in degrees to apply. Default is 0. +Allowed range is from -180 to 180. + +@item saturation +Set the saturation shift. Default is 0. +Allowed range is from -1 to 1. + +@item intensity +Set the intensity shift. Default is 0. +Allowed range is from -1 to 1. + +@item colors +Set which primary and complementary colors are going to be adjusted. +This options is set by providing one or multiple values. +This can select multiple colors at once. By default all colors are selected. +@table @samp +@item r +Adjust reds. +@item y +Adjust yellows. +@item g +Adjust greens. +@item c +Adjust cyans. +@item b +Adjust blues. +@item m +Adjust magentas. +@item a +Adjust all colors. +@end table + +@item strength +Set strength of filtering. Allowed range is from 0 to 100. +Default value is 1. + +@item rw, gw, bw +Set weight for each RGB component. Allowed range is from 0 to 1. +By default is set to 0.333, 0.334, 0.333. +Those options are used in saturation and lightess processing. + +@item lightness +Set preserving lightness, by default is disabled. +Adjusting hues can change lightness from original RGB triplet, +with this option enabled lightness is kept at same value. +@end table + @section hysteresis Grow first stream into second stream by connecting components. @@ -15551,6 +15800,19 @@ Negate (invert) the input video. It accepts the following option: @table @option +@item components +Set components to negate. + +Available values for components are: +@table @samp +@item y +@item u +@item v +@item a +@item r +@item g +@item b +@end table @item negate_alpha With value 1, it negates the alpha component, if present. Default value is 0. @@ -18422,6 +18684,7 @@ scale_cuda=passthrough=0 @end example @end itemize +@anchor{scale_npp} @section scale_npp Use the NVIDIA Performance Primitives (libnpp) to perform scaling and/or pixel @@ -18498,6 +18761,61 @@ This option can be handy if you need to have a video fit within or exceed a defined resolution using @option{force_original_aspect_ratio} but also have encoder restrictions on width or height divisibility. +@item eval +Specify when to evaluate @var{width} and @var{height} expression. It accepts the following values: + +@table @samp +@item init +Only evaluate expressions once during the filter initialization or when a command is processed. + +@item frame +Evaluate expressions for each incoming frame. + +@end table + +@end table + +The values of the @option{w} and @option{h} options are expressions +containing the following constants: + +@table @var +@item in_w +@item in_h +The input width and height + +@item iw +@item ih +These are the same as @var{in_w} and @var{in_h}. + +@item out_w +@item out_h +The output (scaled) width and height + +@item ow +@item oh +These are the same as @var{out_w} and @var{out_h} + +@item a +The same as @var{iw} / @var{ih} + +@item sar +input sample aspect ratio + +@item dar +The input display aspect ratio. Calculated from @code{(iw / ih) * sar}. + +@item n +The (sequential) number of the input frame, starting from 0. +Only available with @code{eval=frame}. + +@item t +The presentation timestamp of the input frame, expressed as a number of +seconds. Only available with @code{eval=frame}. + +@item pos +The position (byte offset) of the frame in the input stream, or NaN if +this information is unavailable and/or meaningless (for example in case of synthetic video). +Only available with @code{eval=frame}. @end table @section scale2ref @@ -18573,6 +18891,61 @@ If the specified expression is not valid, it is kept at its current value. @end table +@section scale2ref_npp + +Use the NVIDIA Performance Primitives (libnpp) to scale (resize) the input +video, based on a reference video. + +See the @ref{scale_npp} filter for available options, scale2ref_npp supports the same +but uses the reference video instead of the main input as basis. scale2ref_npp +also supports the following additional constants for the @option{w} and +@option{h} options: + +@table @var +@item main_w +@item main_h +The main input video's width and height + +@item main_a +The same as @var{main_w} / @var{main_h} + +@item main_sar +The main input video's sample aspect ratio + +@item main_dar, mdar +The main input video's display aspect ratio. Calculated from +@code{(main_w / main_h) * main_sar}. + +@item main_n +The (sequential) number of the main input frame, starting from 0. +Only available with @code{eval=frame}. + +@item main_t +The presentation timestamp of the main input frame, expressed as a number of +seconds. Only available with @code{eval=frame}. + +@item main_pos +The position (byte offset) of the frame in the main input stream, or NaN if +this information is unavailable and/or meaningless (for example in case of synthetic video). +Only available with @code{eval=frame}. +@end table + +@subsection Examples + +@itemize +@item +Scale a subtitle stream (b) to match the main video (a) in size before overlaying +@example +'scale2ref_npp[b][a];[a][b]overlay_cuda' +@end example + +@item +Scale a logo to 1/10th the height of a video, while preserving its display aspect ratio. +@example +[logo-in][video-in]scale2ref_npp=w=oh*mdar:h=ih/10[logo-out][video-out] +@end example +@end itemize + @section scharr Apply scharr operator to input video stream. @@ -21610,6 +21983,11 @@ Set if input video is transposed. Boolean value, by default disabled. @item out_trans Set if output video needs to be transposed. Boolean value, by default disabled. +@item h_offset +@item v_offset +Set output horizontal/vertical off-axis offset. Default is set to 0. +Allowed range is from -1 to 1. + @item alpha_mask Build mask in alpha plane for all unmapped pixels by marking them fully transparent. Boolean value, by default disabled. @@ -21706,20 +22084,25 @@ Default is universal. @section varblur Apply variable blur filter by using 2nd video stream to set blur radius. +The 2nd stream must have the same dimensions. This filter accepts the following options: @table @option @item min_r -Set min allowed radius. By default is 0. Allowed range is from 0 to 254. +Set min allowed radius. Allowed range is from 0 to 254. Default is 0. @item max_r -Set max allowed radius. By default is 8. Allowed range is from 1 to 255. +Set max allowed radius. Allowed range is from 1 to 255. Default is 8. @item planes -Set which planes to process. By default all are used. +Set which planes to process. By default, all are used. @end table The @code{varblur} filter also supports the @ref{framesync} options. +@subsection Commands + +This filter supports all the above options as @ref{commands}. + @section vectorscope Display 2 color component values in the two dimensional graph (which is called @@ -22683,6 +23066,7 @@ Default transition effect is fade. @item duration Set cross fade duration in seconds. +Range is 0 to 60 seconds. Default duration is 1 second. @item offset @@ -25043,6 +25427,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{colorspectrum} @anchor{haldclutsrc} @anchor{nullsrc} @anchor{pal75bars} @@ -25053,7 +25438,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, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc +@section allrgb, allyuv, color, colorspectrum, haldclutsrc, nullsrc, pal75bars, pal100bars, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors. @@ -25061,6 +25446,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{colorspectrum} source provides a color spectrum input. + The @code{haldclutsrc} source provides an identity Hald CLUT. See also @ref{haldclut} filter. @@ -25152,6 +25539,16 @@ Set the number of decimals to show in the timestamp, only available in the The displayed timestamp value will correspond to the original timestamp value multiplied by the power of 10 of the specified value. Default value is 0. + +@item type +Set the type of the color spectrum, only available in the +@code{colorspectrum} source. Can be one of the following: + +@table @samp +@item black +@item white +@item all +@end table @end table @subsection Examples @@ -28156,6 +28553,18 @@ changed, so it will generate non monotonically increasing timestamps. Specifies the time difference between frames above which the point is considered a timestamp discontinuity which is removed by adjusting the later timestamps. + +@item dec_threads +Specifies the number of threads for decoding + +@item format_opts +Specify format options for the opened file. Format options can be specified +as a list of @var{key}=@var{value} pairs separated by ':'. The following example +shows how to add protocol_whitelist and protocol_blacklist options: +@example +ffplay -f lavfi +"movie=filename='1.sdp':format_opts='protocol_whitelist=file,rtp,udp\:protocol_blacklist=http'" +@end example @end table It allows overlaying a second video on top of the main input of diff --git a/doc/indevs.texi b/doc/indevs.texi index 5be647f70a..9d8020311a 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -625,6 +625,12 @@ Save the currently used video capture filter device and its parameters (if the filter supports it) to a file. If a file with the same name exists it will be overwritten. +@item use_video_device_timestamps +If set to @option{false}, the timestamp for video frames will be +derived from the wallclock instead of the timestamp provided by +the capture device. This allows working around devices that +provide unreliable timestamps. + @end table @subsection Examples diff --git a/doc/muxers.texi b/doc/muxers.texi index 7338e8d5d3..c49ae3a17b 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -362,12 +362,13 @@ Ignore IO errors during open and write. Useful for long-duration runs with netwo @item lhls @var{lhls} Enable Low-latency HLS(LHLS). Adds #EXT-X-PREFETCH tag with current segment's URI. -Apple doesn't have an official spec for LHLS. Meanwhile hls.js player folks are -trying to standardize a open LHLS spec. The draft spec is available in https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md -This option will also try to comply with the above open spec, till Apple's spec officially supports it. -Applicable only when @var{streaming} and @var{hls_playlist} options are enabled. +hls.js player folks are trying to standardize an open LHLS spec. The draft spec is available in https://github.com/video-dev/hlsjs-rfcs/blob/lhls-spec/proposals/0001-lhls.md +This option tries to comply with the above open spec. +It enables @var{streaming} and @var{hls_playlist} options automatically. This is an experimental feature. +Note: This is not Apple's version LHLS. See @url{https://datatracker.ietf.org/doc/html/draft-pantos-hls-rfc8216bis} + @item ldash @var{ldash} Enable Low-latency Dash by constraining the presence and values of some elements. @@ -798,6 +799,7 @@ were recently referenced in the playlist. Default value is 1, meaning segments o Set output format options using a :-separated list of key=value parameters. Values containing @code{:} special characters must be escaped. +@code{hls_ts_options} is deprecated, use hls_segment_options instead of it.. @item hls_start_number_source Start the playlist sequence number (@code{#EXT-X-MEDIA-SEQUENCE}) according to the specified source. @@ -918,6 +920,10 @@ This example will create a directory hierarchy 2016/02/15 (if any of them do not produce the playlist, @file{out.m3u8}, and segment files: @file{2016/02/15/file-20160215-1455569023.ts}, @file{2016/02/15/file-20160215-1455569024.ts}, etc. +@item hls_segment_options @var{options_list} +Set output format options using a :-separated list of key=value +parameters. Values containing @code{:} special characters must be +escaped. @item hls_key_info_file @var{key_info_file} Use the information in @var{key_info_file} for segment encryption. The first @@ -1561,6 +1567,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 diff --git a/doc/protocols.texi b/doc/protocols.texi index c100f23f17..d207df0b52 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1087,6 +1087,10 @@ set to 1) or to a default remote address (if set to 0). @item localport=@var{n} Set the local RTP port to @var{n}. +@item localaddr=@var{addr} +Local IP address of a network interface used for sending packets or joining +multicast groups. + @item timeout=@var{n} Set timeout (in microseconds) of socket I/O operations to @var{n}. diff --git a/doc/t2h.pm b/doc/t2h.pm index e83d564a65..d07d974286 100644 --- a/doc/t2h.pm +++ b/doc/t2h.pm @@ -126,8 +126,16 @@ foreach my $command (keys(%Texinfo::Common::sectioning_commands), 'node') { texinfo_register_command_formatting($command, \&ffmpeg_heading_command); } +# determine if texinfo is at least version 6.8 +my $program_version_num = version->declare(get_conf('PACKAGE_VERSION'))->numify; +my $program_version_6_8 = $program_version_num >= 6.008000; + # print the TOC where @contents is used -set_from_init_file('INLINE_CONTENTS', 1); +if ($program_version_6_8) { + set_from_init_file('CONTENTS_OUTPUT_LOCATION', 'inline'); +} else { + set_from_init_file('INLINE_CONTENTS', 1); +} # make chapters

set_from_init_file('CHAPTER_HEADER_LEVEL', 2); @@ -184,7 +192,11 @@ EOT return $head1 . $head_title . $head2 . $head_title . $head3; } -texinfo_register_formatting_function('begin_file', \&ffmpeg_begin_file); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_begin_file', \&ffmpeg_begin_file); +} else { + texinfo_register_formatting_function('begin_file', \&ffmpeg_begin_file); +} sub ffmpeg_program_string($) { @@ -201,7 +213,11 @@ sub ffmpeg_program_string($) $self->gdt('This document was generated automatically.')); } } -texinfo_register_formatting_function('program_string', \&ffmpeg_program_string); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_program_string', \&ffmpeg_program_string); +} else { + texinfo_register_formatting_function('program_string', \&ffmpeg_program_string); +} # Customized file ending sub ffmpeg_end_file($) @@ -220,7 +236,11 @@ EOT EOT return $program_text . $footer; } -texinfo_register_formatting_function('end_file', \&ffmpeg_end_file); +if ($program_version_6_8) { + texinfo_register_formatting_function('format_end_file', \&ffmpeg_end_file); +} else { + texinfo_register_formatting_function('end_file', \&ffmpeg_end_file); +} # Dummy title command # Ignore title. Title is handled through ffmpeg_begin_file(). diff --git a/ffbuild/arch.mak b/ffbuild/arch.mak index e09006efca..997e31e85e 100644 --- a/ffbuild/arch.mak +++ b/ffbuild/arch.mak @@ -8,7 +8,9 @@ OBJS-$(HAVE_MIPSFPU) += $(MIPSFPU-OBJS) $(MIPSFPU-OBJS-yes) OBJS-$(HAVE_MIPSDSP) += $(MIPSDSP-OBJS) $(MIPSDSP-OBJS-yes) OBJS-$(HAVE_MIPSDSPR2) += $(MIPSDSPR2-OBJS) $(MIPSDSPR2-OBJS-yes) OBJS-$(HAVE_MSA) += $(MSA-OBJS) $(MSA-OBJS-yes) -OBJS-$(HAVE_MMI) += $(MMI-OBJS) $(MMI-OBJS-yes) +OBJS-$(HAVE_MMI) += $(MMI-OBJS) $(MMI-OBJS-yes) +OBJS-$(HAVE_LSX) += $(LSX-OBJS) $(LSX-OBJS-yes) +OBJS-$(HAVE_LASX) += $(LASX-OBJS) $(LASX-OBJS-yes) OBJS-$(HAVE_ALTIVEC) += $(ALTIVEC-OBJS) $(ALTIVEC-OBJS-yes) OBJS-$(HAVE_VSX) += $(VSX-OBJS) $(VSX-OBJS-yes) diff --git a/ffbuild/common.mak b/ffbuild/common.mak index 268ae61154..42f7b23641 100644 --- a/ffbuild/common.mak +++ b/ffbuild/common.mak @@ -59,6 +59,8 @@ COMPILE_HOSTC = $(call COMPILE,HOSTCC) COMPILE_NVCC = $(call COMPILE,NVCC) COMPILE_MMI = $(call COMPILE,CC,MMIFLAGS) COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) +COMPILE_LSX = $(call COMPILE,CC,LSXFLAGS) +COMPILE_LASX = $(call COMPILE,CC,LASXFLAGS) %_mmi.o: %_mmi.c $(COMPILE_MMI) @@ -66,6 +68,12 @@ COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) %_msa.o: %_msa.c $(COMPILE_MSA) +%_lsx.o: %_lsx.c + $(COMPILE_LSX) + +%_lasx.o: %_lasx.c + $(COMPILE_LASX) + %.o: %.c $(COMPILE_C) @@ -104,6 +112,15 @@ COMPILE_MSA = $(call COMPILE,CC,MSAFLAGS) $(BIN2CEXE): ffbuild/bin2c_host.o $(HOSTLD) $(HOSTLDFLAGS) $(HOSTLD_O) $^ $(HOSTEXTRALIBS) +%.metal.air: %.metal + $(METALCC) $< -o $@ + +%.metallib: %.metal.air + $(METALLIB) --split-module-without-linking $< -o $@ + +%.metallib.c: %.metallib $(BIN2CEXE) + $(BIN2C) $< $@ $(subst .,_,$(basename $(notdir $@))) + %.ptx: %.cu $(SRC_PATH)/compat/cuda/cuda_runtime.h $(COMPILE_NVCC) @@ -140,6 +157,8 @@ include $(SRC_PATH)/ffbuild/arch.mak OBJS += $(OBJS-yes) SLIBOBJS += $(SLIBOBJS-yes) +SHLIBOBJS += $(SHLIBOBJS-yes) +STLIBOBJS += $(STLIBOBJS-yes) FFLIBS := $($(NAME)_FFLIBS) $(FFLIBS-yes) $(FFLIBS) TESTPROGS += $(TESTPROGS-yes) @@ -148,6 +167,8 @@ FFEXTRALIBS := $(LDLIBS:%=$(LD_LIB)) $(foreach lib,EXTRALIBS-$(NAME) $(FFLIBS:%= OBJS := $(sort $(OBJS:%=$(SUBDIR)%)) SLIBOBJS := $(sort $(SLIBOBJS:%=$(SUBDIR)%)) +SHLIBOBJS := $(sort $(SHLIBOBJS:%=$(SUBDIR)%)) +STLIBOBJS := $(sort $(STLIBOBJS:%=$(SUBDIR)%)) TESTOBJS := $(TESTOBJS:%=$(SUBDIR)tests/%) $(TESTPROGS:%=$(SUBDIR)tests/%.o) TESTPROGS := $(TESTPROGS:%=$(SUBDIR)tests/%$(EXESUF)) HOSTOBJS := $(HOSTPROGS:%=$(SUBDIR)%.o) @@ -183,10 +204,12 @@ $(OBJS): | $(sort $(dir $(OBJS))) $(HOBJS): | $(sort $(dir $(HOBJS))) $(HOSTOBJS): | $(sort $(dir $(HOSTOBJS))) $(SLIBOBJS): | $(sort $(dir $(SLIBOBJS))) +$(SHLIBOBJS): | $(sort $(dir $(SHLIBOBJS))) +$(STLIBOBJS): | $(sort $(dir $(STLIBOBJS))) $(TESTOBJS): | $(sort $(dir $(TESTOBJS))) $(TOOLOBJS): | tools -OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(TESTOBJS)) +OUTDIRS := $(OUTDIRS) $(dir $(OBJS) $(HOBJS) $(HOSTOBJS) $(SLIBOBJS) $(SHLIBOBJS) $(STLIBOBJS) $(TESTOBJS)) CLEANSUFFIXES = *.d *.gcda *.gcno *.h.c *.ho *.map *.o *.pc *.ptx *.ptx.gz *.ptx.c *.ver *.version *$(DEFAULT_X86ASMD).asm *~ *.ilk *.pdb LIBSUFFIXES = *.a *.lib *.so *.so.* *.dylib *.dll *.def *.dll.a @@ -198,4 +221,4 @@ endef $(eval $(RULES)) --include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) +-include $(wildcard $(OBJS:.o=.d) $(HOSTOBJS:.o=.d) $(TESTOBJS:.o=.d) $(HOBJS:.o=.d) $(SHLIBOBJS:.o=.d) $(STLIBOBJS:.o=.d) $(SLIBOBJS:.o=.d)) $(OBJS:.o=$(DEFAULT_X86ASMD).d) diff --git a/ffbuild/library.mak b/ffbuild/library.mak index 612bacb980..ad09f20da9 100644 --- a/ffbuild/library.mak +++ b/ffbuild/library.mak @@ -14,10 +14,26 @@ INSTHEADERS := $(INSTHEADERS) $(HEADERS:%=$(SUBDIR)%) all-$(CONFIG_STATIC): $(SUBDIR)$(LIBNAME) $(SUBDIR)lib$(FULLNAME).pc all-$(CONFIG_SHARED): $(SUBDIR)$(SLIBNAME) $(SUBDIR)lib$(FULLNAME).pc -LIBOBJS := $(OBJS) $(SUBDIR)%.h.o $(TESTOBJS) +LIBOBJS := $(OBJS) $(SHLIBOBJS) $(STLIBOBJS) $(SUBDIR)%.h.o $(TESTOBJS) $(LIBOBJS) $(LIBOBJS:.o=.s) $(LIBOBJS:.o=.i): CPPFLAGS += -DHAVE_AV_CONFIG_H -$(SUBDIR)$(LIBNAME): $(OBJS) +ifdef CONFIG_SHARED +# In case both shared libs and static libs are enabled, it can happen +# that a user might want to link e.g. libavformat statically, but +# libavcodec and the other libs dynamically. In this case +# libavformat won't be able to access libavcodec's internal symbols, +# so that they have to be duplicated into the archive just like +# for purely shared builds. +# Test programs are always statically linked against their library +# to be able to access their library's internals, even with shared builds. +# Yet linking against dependend libraries still uses dynamic linking. +# This means that we are in the scenario described above. +# In case only static libs are used, the linker will only use +# one of these copies; this depends on the duplicated object files +# containing exactly the same symbols. +OBJS += $(SHLIBOBJS) +endif +$(SUBDIR)$(LIBNAME): $(OBJS) $(STLIBOBJS) $(RM) $@ $(AR) $(ARFLAGS) $(AR_O) $^ $(RANLIB) $@ @@ -48,7 +64,7 @@ $(SUBDIR)lib$(NAME).ver: $(SUBDIR)lib$(NAME).v $(OBJS) $(SUBDIR)$(SLIBNAME): $(SUBDIR)$(SLIBNAME_WITH_MAJOR) $(Q)cd ./$(SUBDIR) && $(LN_S) $(SLIBNAME_WITH_MAJOR) $(SLIBNAME) -$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver +$(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SHLIBOBJS) $(SLIBOBJS) $(SUBDIR)lib$(NAME).ver $(SLIB_CREATE_DEF_CMD) $$(LD) $(SHFLAGS) $(LDFLAGS) $(LDSOFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS) $(SLIB_EXTRA_CMD) diff --git a/fftools/Makefile b/fftools/Makefile index 5234932ab0..da420786eb 100644 --- a/fftools/Makefile +++ b/fftools/Makefile @@ -10,10 +10,6 @@ ALLAVPROGS = $(AVBASENAMES:%=%$(PROGSSUF)$(EXESUF)) ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF)) OBJS-ffmpeg += fftools/ffmpeg_opt.o fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o -ifndef CONFIG_VIDEOTOOLBOX -OBJS-ffmpeg-$(CONFIG_VDA) += fftools/ffmpeg_videotoolbox.o -endif -OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += fftools/ffmpeg_videotoolbox.o define DOFFTOOL OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes) diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index cba96eaadd..64ff613594 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1770,7 +1770,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) "..H.. = Hardware accelerated format\n" "...P. = Paletted format\n" "....B = Bitstream format\n" - "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL\n" + "FLAGS NAME NB_COMPONENTS BITS_PER_PIXEL BIT_DEPTHS\n" "-----\n"); #if !CONFIG_SWSCALE @@ -1780,7 +1780,7 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) 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 %2d\n", + 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' : '.', @@ -1788,7 +1788,12 @@ int show_pix_fmts(void *optctx, const char *opt, const char *arg) pix_desc->flags & AV_PIX_FMT_FLAG_BITSTREAM ? 'B' : '.', pix_desc->name, pix_desc->nb_components, - av_get_bits_per_pixel(pix_desc)); + 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; } @@ -1831,6 +1836,16 @@ int show_sample_fmts(void *optctx, const char *opt, const char *arg) 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; @@ -2122,7 +2137,7 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, AVFormatContext *s, AVStream *st, const AVCodec *codec) { AVDictionary *ret = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int flags = s->oformat ? AV_OPT_FLAG_ENCODING_PARAM : AV_OPT_FLAG_DECODING_PARAM; char prefix = 0; @@ -2188,7 +2203,7 @@ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, if (!opts) { av_log(NULL, AV_LOG_ERROR, "Could not alloc memory for stream options.\n"); - return NULL; + exit_program(1); } for (i = 0; i < s->nb_streams; i++) opts[i] = filter_codec_opts(codec_opts, s->streams[i]->codecpar->codec_id, @@ -2215,6 +2230,18 @@ void *grow_array(void *array, int elem_size, int *size, int new_size) return array; } +void *allocate_array_elem(void *ptr, size_t elem_size, int *nb_elems) +{ + void *new_elem; + + if (!(new_elem = av_mallocz(elem_size)) || + av_dynarray_add_nofree(ptr, nb_elems, new_elem) < 0) { + av_log(NULL, AV_LOG_ERROR, "Could not alloc buffer.\n"); + exit_program(1); + } + return new_elem; +} + double get_rotation(int32_t *displaymatrix) { double theta = 0; @@ -2233,9 +2260,29 @@ double get_rotation(int32_t *displaymatrix) } #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, i; + int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_INPUT_DEVICE(fmt->priv_class->category)) @@ -2247,10 +2294,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) goto fail; } - for (i = 0; i < device_list->nb_devices; i++) { - printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); - } + print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); @@ -2259,7 +2303,7 @@ static int print_device_sources(const AVInputFormat *fmt, AVDictionary *opts) static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) { - int ret, i; + int ret; AVDeviceInfoList *device_list = NULL; if (!fmt || !fmt->priv_class || !AV_IS_OUTPUT_DEVICE(fmt->priv_class->category)) @@ -2271,10 +2315,7 @@ static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *opts) goto fail; } - for (i = 0; i < device_list->nb_devices; i++) { - printf("%c %s [%s]\n", device_list->default_device == i ? '*' : ' ', - device_list->devices[i]->device_name, device_list->devices[i]->device_description); - } + print_device_list(device_list); fail: avdevice_free_list_devices(&device_list); diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 2a6bc2cfb2..11e3d0f1ae 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -241,6 +241,7 @@ void show_help_options(const OptionDef *options, const char *msg, int req_flags, { "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" }, \ @@ -432,8 +433,8 @@ AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec_id, * Each dictionary will contain the options from codec_opts which can * be applied to the corresponding stream codec context. * - * @return pointer to the created array of dictionaries, NULL if it - * cannot be created + * @return pointer to the created array of dictionaries. + * Calls exit() on failure. */ AVDictionary **setup_find_stream_info_opts(AVFormatContext *s, AVDictionary *codec_opts); @@ -580,6 +581,11 @@ int show_layouts(void *optctx, const char *opt, const char *arg); */ 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. @@ -625,11 +631,28 @@ FILE *get_preset_file(char *filename, size_t filename_size, */ void *grow_array(void *array, int elem_size, int *size, int new_size); +/** + * Atomically add a new element to an array of pointers, i.e. allocate + * a new entry, reallocate the array of pointers and make the new last + * member of this array point to the newly allocated buffer. + * Calls exit() on failure. + * + * @param array array of pointers to reallocate + * @param elem_size size of the new element to allocate + * @param nb_elems pointer to the number of elements of the array array; + * *nb_elems will be incremented by one by this function. + * @return pointer to the newly allocated entry + */ +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) +#define ALLOC_ARRAY_ELEM(array, nb_elems)\ + allocate_array_elem(&array, sizeof(*array[0]), &nb_elems) + #define GET_PIX_FMT_NAME(pix_fmt)\ const char *name = av_get_pix_fmt_name(pix_fmt); diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 4876e55284..1379019759 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -557,9 +557,6 @@ static void ffmpeg_cleanup(int ret) avfilter_inout_free(&ofilter->out_tmp); av_freep(&ofilter->name); - av_freep(&ofilter->formats); - av_freep(&ofilter->channel_layouts); - av_freep(&ofilter->sample_rates); av_freep(&fg->outputs[j]); } av_freep(&fg->outputs); @@ -635,7 +632,6 @@ static void ffmpeg_cleanup(int ret) InputStream *ist = input_streams[i]; av_frame_free(&ist->decoded_frame); - av_frame_free(&ist->filter_frame); av_packet_free(&ist->pkt); av_dict_free(&ist->decoder_opts); avsubtitle_free(&ist->prev_sub.subtitle); @@ -679,7 +675,7 @@ static void ffmpeg_cleanup(int ret) void remove_avoptions(AVDictionary **a, AVDictionary *b) { - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; while ((t = av_dict_get(b, "", t, AV_DICT_IGNORE_SUFFIX))) { av_dict_set(a, t->key, NULL, AV_DICT_MATCH_CASE); @@ -688,7 +684,7 @@ void remove_avoptions(AVDictionary **a, AVDictionary *b) void assert_avoptions(AVDictionary *m) { - AVDictionaryEntry *t; + const AVDictionaryEntry *t; if ((t = av_dict_get(m, "", NULL, AV_DICT_IGNORE_SUFFIX))) { av_log(NULL, AV_LOG_FATAL, "Option %s not found.\n", t->key); exit_program(1); @@ -756,14 +752,13 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u 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; - int new_size = are_we_over_size ? - FFMIN(2 * av_fifo_size(ost->muxing_queue), - ost->max_muxing_queue_size) : - 2 * av_fifo_size(ost->muxing_queue); + 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 <= av_fifo_size(ost->muxing_queue)) { + 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); @@ -878,10 +873,11 @@ static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int u static void close_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; + AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base; ost->finished |= ENCODER_FINISHED; if (of->shortest) { - int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, ost->enc_ctx->time_base, AV_TIME_BASE_Q); + int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q); of->recording_time = FFMIN(of->recording_time, end); } } @@ -1151,11 +1147,12 @@ static void do_subtitle_out(OutputFile *of, } } +/* May modify/reset next_picture */ static void do_video_out(OutputFile *of, OutputStream *ost, AVFrame *next_picture) { - int ret, format_video_sync; + int ret; AVPacket *pkt = ost->pkt; AVCodecContext *enc = ost->enc_ctx; AVRational frame_rate; @@ -1202,28 +1199,10 @@ static void do_video_out(OutputFile *of, nb0_frames = 0; // tracks the number of times the PREVIOUS frame should be duplicated, mostly for variable framerate (VFR) nb_frames = 1; - format_video_sync = video_sync_method; - if (format_video_sync == VSYNC_AUTO) { - if(!strcmp(of->ctx->oformat->name, "avi")) { - format_video_sync = VSYNC_VFR; - } else - format_video_sync = (of->ctx->oformat->flags & AVFMT_VARIABLE_FPS) ? ((of->ctx->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : VSYNC_CFR; - if ( ist - && format_video_sync == VSYNC_CFR - && input_files[ist->file_index]->ctx->nb_streams == 1 - && input_files[ist->file_index]->input_ts_offset == 0) { - format_video_sync = VSYNC_VSCFR; - } - if (format_video_sync == VSYNC_CFR && copy_ts) { - format_video_sync = VSYNC_VSCFR; - } - } - ost->is_cfr = (format_video_sync == VSYNC_CFR || format_video_sync == VSYNC_VSCFR); - if (delta0 < 0 && delta > 0 && - format_video_sync != VSYNC_PASSTHROUGH && - format_video_sync != VSYNC_DROP) { + ost->vsync_method != VSYNC_PASSTHROUGH && + ost->vsync_method != VSYNC_DROP) { if (delta0 < -0.6) { av_log(NULL, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); } else @@ -1233,7 +1212,7 @@ static void do_video_out(OutputFile *of, delta0 = 0; } - switch (format_video_sync) { + switch (ost->vsync_method) { case VSYNC_VSCFR: if (ost->frame_number == 0 && delta0 >= 0.5) { av_log(NULL, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); @@ -1304,7 +1283,7 @@ static void do_video_out(OutputFile *of, int forced_keyframe = 0; double pts_time; - if (i < nb0_frames && ost->last_frame) { + if (i < nb0_frames && ost->last_frame->buf[0]) { in_picture = ost->last_frame; } else in_picture = next_picture; @@ -1432,13 +1411,9 @@ static void do_video_out(OutputFile *of, do_video_stats(ost, frame_size); } - if (!ost->last_frame) - ost->last_frame = av_frame_alloc(); av_frame_unref(ost->last_frame); - if (next_picture && ost->last_frame) - av_frame_ref(ost->last_frame, next_picture); - else - av_frame_free(&ost->last_frame); + if (next_picture) + av_frame_move_ref(ost->last_frame, next_picture); return; error: @@ -1497,13 +1472,13 @@ static void do_video_stats(OutputStream *ost, int frame_size) static void finish_output_stream(OutputStream *ost) { OutputFile *of = output_files[ost->file_index]; - int i; + AVRational time_base = ost->stream_copy ? ost->mux_timebase : ost->enc_ctx->time_base; ost->finished = ENCODER_FINISHED | MUXER_FINISHED; if (of->shortest) { - for (i = 0; i < of->ctx->nb_streams; i++) - output_streams[of->ost_index + i]->finished = ENCODER_FINISHED | MUXER_FINISHED; + int64_t end = av_rescale_q(ost->sync_opts - ost->first_pts, time_base, AV_TIME_BASE_Q); + of->recording_time = FFMIN(of->recording_time, end); } } @@ -1542,9 +1517,6 @@ static int reap_filters(int flush) if (av_buffersink_get_type(filter) == AVMEDIA_TYPE_AUDIO) init_output_stream_wrapper(ost, NULL, 1); - if (!ost->filtered_frame && !(ost->filtered_frame = av_frame_alloc())) { - return AVERROR(ENOMEM); - } filtered_frame = ost->filtered_frame; while (1) { @@ -2168,10 +2140,6 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p } } - /* force the input stream PTS */ - if (ost->enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) - ost->sync_opts++; - if (av_packet_ref(opkt, pkt) < 0) exit_program(1); @@ -2195,6 +2163,8 @@ static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVPacket *p opkt->duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->mux_timebase); + ost->sync_opts += opkt->duration; + output_packet(of, opkt, ost, 0); } @@ -2248,11 +2218,15 @@ static int ifilter_has_all_input_formats(FilterGraph *fg) return 1; } -static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) +static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int keep_reference) { FilterGraph *fg = ifilter->graph; AVFrameSideData *sd; - int need_reinit, ret, i; + int need_reinit, ret; + int buffersrc_flags = AV_BUFFERSRC_FLAG_PUSH; + + if (keep_reference) + buffersrc_flags |= AV_BUFFERSRC_FLAG_KEEP_REF; /* determine if the parameters for this input changed */ need_reinit = ifilter->format != frame->format; @@ -2290,23 +2264,20 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) /* (re)init the graph if possible, otherwise buffer the frame and return */ if (need_reinit || !fg->graph) { - for (i = 0; i < fg->nb_inputs; i++) { - if (!ifilter_has_all_input_formats(fg)) { - AVFrame *tmp = av_frame_clone(frame); - if (!tmp) - return AVERROR(ENOMEM); - av_frame_unref(frame); + if (!ifilter_has_all_input_formats(fg)) { + AVFrame *tmp = av_frame_clone(frame); + 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; - } + 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; } + av_fifo_generic_write(ifilter->frame_queue, &tmp, sizeof(tmp), NULL); + return 0; } ret = reap_filters(1); @@ -2322,7 +2293,7 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) } } - ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, AV_BUFFERSRC_FLAG_PUSH); + ret = av_buffersrc_add_frame_flags(ifilter->filter, frame, buffersrc_flags); if (ret < 0) { if (ret != AVERROR_EOF) av_log(NULL, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); @@ -2385,18 +2356,10 @@ static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacke static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) { int i, ret; - AVFrame *f; av_assert1(ist->nb_filters > 0); /* ensure ret is initialized */ for (i = 0; i < ist->nb_filters; i++) { - if (i < ist->nb_filters - 1) { - f = ist->filter_frame; - ret = av_frame_ref(f, decoded_frame); - if (ret < 0) - break; - } else - f = decoded_frame; - ret = ifilter_send_frame(ist->filters[i], f); + ret = ifilter_send_frame(ist->filters[i], decoded_frame, i < ist->nb_filters - 1); if (ret == AVERROR_EOF) ret = 0; /* ignore */ if (ret < 0) { @@ -2411,17 +2374,11 @@ static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame) static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, int *decode_failed) { - AVFrame *decoded_frame; + AVFrame *decoded_frame = ist->decoded_frame; AVCodecContext *avctx = ist->dec_ctx; int ret, err = 0; AVRational decoded_frame_tb; - if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - decoded_frame = ist->decoded_frame; - update_benchmark(NULL); ret = decode(avctx, decoded_frame, got_output, pkt); update_benchmark("decode_audio %d.%d", ist->file_index, ist->st->index); @@ -2458,6 +2415,11 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, decoded_frame->pts = ist->dts; decoded_frame_tb = AV_TIME_BASE_Q; } + if (pkt && pkt->duration && ist->prev_pkt_pts != AV_NOPTS_VALUE && + pkt->pts != AV_NOPTS_VALUE && pkt->pts - ist->prev_pkt_pts > pkt->duration) + ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + if (pkt) + ist->prev_pkt_pts = pkt->pts; if (decoded_frame->pts != AV_NOPTS_VALUE) decoded_frame->pts = av_rescale_delta(decoded_frame_tb, decoded_frame->pts, (AVRational){1, avctx->sample_rate}, decoded_frame->nb_samples, &ist->filter_in_rescale_delta_last, @@ -2465,7 +2427,6 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, ist->nb_samples = decoded_frame->nb_samples; err = send_frame_to_filters(ist, decoded_frame); - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } @@ -2473,7 +2434,7 @@ static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output, static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_t *duration_pts, int eof, int *decode_failed) { - AVFrame *decoded_frame; + AVFrame *decoded_frame = ist->decoded_frame; int i, ret = 0, err = 0; int64_t best_effort_timestamp; int64_t dts = AV_NOPTS_VALUE; @@ -2484,11 +2445,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ if (!eof && pkt && pkt->size == 0) return 0; - if (!ist->decoded_frame && !(ist->decoded_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - if (!ist->filter_frame && !(ist->filter_frame = av_frame_alloc())) - return AVERROR(ENOMEM); - decoded_frame = ist->decoded_frame; if (ist->dts != AV_NOPTS_VALUE) dts = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base); if (pkt) { @@ -2596,7 +2552,6 @@ static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output, int64_ err = send_frame_to_filters(ist, decoded_frame); fail: - av_frame_unref(ist->filter_frame); av_frame_unref(decoded_frame); return err < 0 ? err : ret; } @@ -2880,17 +2835,17 @@ static int process_input_packet(InputStream *ist, const AVPacket *pkt, int no_eo return !eof_reached; } -static void print_sdp(void) +static int print_sdp(void) { char sdp[16384]; int i; - int j; + int j, ret; AVIOContext *sdp_pb; AVFormatContext **avc; for (i = 0; i < nb_output_files; i++) { if (!output_files[i]->header_written) - return; + return 0; } avc = av_malloc_array(nb_output_files, sizeof(*avc)); @@ -2903,26 +2858,34 @@ static void print_sdp(void) } } - if (!j) + if (!j) { + av_log(NULL, AV_LOG_ERROR, "No output streams in the SDP.\n"); + ret = AVERROR(EINVAL); goto fail; + } - av_sdp_create(avc, j, sdp, sizeof(sdp)); + 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 { - if (avio_open2(&sdp_pb, sdp_filename, AVIO_FLAG_WRITE, &int_cb, NULL) < 0) { + 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); - } else { - avio_print(sdp_pb, sdp); - avio_closep(&sdp_pb); - av_freep(&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) @@ -2952,12 +2915,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat break; } } - if (config) { - if (config->device_type != ist->hwaccel_device_type) { - // Different hwaccel offered, ignore. - continue; - } - + if (config && config->device_type == ist->hwaccel_device_type) { ret = hwaccel_decode_init(s); if (ret < 0) { if (ist->hwaccel_id == HWACCEL_GENERIC) { @@ -2970,57 +2928,15 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat } continue; } - } else { - const HWAccel *hwaccel = NULL; - int i; - for (i = 0; hwaccels[i].name; i++) { - if (hwaccels[i].pix_fmt == *p) { - hwaccel = &hwaccels[i]; - break; - } - } - if (!hwaccel) { - // No hwaccel supporting this pixfmt. - continue; - } - if (hwaccel->id != ist->hwaccel_id) { - // Does not match requested hwaccel. - continue; - } - ret = hwaccel->init(s); - if (ret < 0) { - av_log(NULL, AV_LOG_FATAL, - "%s hwaccel requested for input stream #%d:%d, " - "but cannot be initialized.\n", hwaccel->name, - ist->file_index, ist->st->index); - return AV_PIX_FMT_NONE; - } + ist->hwaccel_pix_fmt = *p; + break; } - - if (ist->hw_frames_ctx) { - s->hw_frames_ctx = av_buffer_ref(ist->hw_frames_ctx); - if (!s->hw_frames_ctx) - return AV_PIX_FMT_NONE; - } - - ist->hwaccel_pix_fmt = *p; - break; } return *p; } -static int get_buffer(AVCodecContext *s, AVFrame *frame, int flags) -{ - InputStream *ist = s->opaque; - - if (ist->hwaccel_get_buffer && frame->format == ist->hwaccel_pix_fmt) - return ist->hwaccel_get_buffer(s, frame, flags); - - return avcodec_default_get_buffer2(s, frame, flags); -} - static int init_input_stream(int ist_index, char *error, int error_len) { int ret; @@ -3036,7 +2952,6 @@ 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; - ist->dec_ctx->get_buffer2 = get_buffer; #if LIBAVCODEC_VERSION_MAJOR < 60 FF_DISABLE_DEPRECATION_WARNINGS ist->dec_ctx->thread_safe_callbacks = 1; @@ -3110,8 +3025,6 @@ static int check_init_output_file(OutputFile *of, int file_index) 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, @@ -3126,8 +3039,13 @@ static int check_init_output_file(OutputFile *of, int file_index) av_dump_format(of->ctx, file_index, of->ctx->url, 1); nb_output_dumped++; - if (sdp_filename || want_sdp) - print_sdp(); + 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++) { @@ -3244,9 +3162,6 @@ static int init_output_stream_streamcopy(OutputStream *ost) if (ost->st->duration <= 0 && ist->st->duration > 0) ost->st->duration = av_rescale_q(ist->st->duration, ist->st->time_base, ost->st->time_base); - // copy disposition - ost->st->disposition = ist->st->disposition; - if (ist->st->nb_side_data) { for (i = 0; i < ist->st->nb_side_data; i++) { const AVPacketSideData *sd_src = &ist->st->side_data[i]; @@ -3302,7 +3217,7 @@ static int init_output_stream_streamcopy(OutputStream *ost) static void set_encoder_id(OutputFile *of, OutputStream *ost) { - AVDictionaryEntry *e; + const AVDictionaryEntry *e; uint8_t *encoder_string; int encoder_string_len; @@ -3434,40 +3349,17 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *dec_ctx = NULL; AVFormatContext *oc = output_files[ost->file_index]->ctx; - int j, ret; + int ret; set_encoder_id(output_files[ost->file_index], ost); - // Muxers use AV_PKT_DATA_DISPLAYMATRIX to signal rotation. On the other - // hand, the legacy API makes demuxers set "rotate" metadata entries, - // which have to be filtered out to prevent leaking them to output files. - av_dict_set(&ost->st->metadata, "rotate", NULL, 0); - if (ist) { - ost->st->disposition = ist->st->disposition; - dec_ctx = ist->dec_ctx; - - enc_ctx->chroma_sample_location = dec_ctx->chroma_sample_location; - } else { - for (j = 0; j < oc->nb_streams; j++) { - AVStream *st = oc->streams[j]; - if (st != ost->st && st->codecpar->codec_type == ost->st->codecpar->codec_type) - break; - } - if (j == oc->nb_streams) - if (ost->st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO || - ost->st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) - ost->st->disposition = AV_DISPOSITION_DEFAULT; } if (enc_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (!ost->frame_rate.num) ost->frame_rate = av_buffersink_get_frame_rate(ost->filter->filter); - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->framerate; - if (ist && !ost->frame_rate.num) - ost->frame_rate = ist->st->r_frame_rate; if (ist && !ost->frame_rate.num && !ost->max_frame_rate.num) { ost->frame_rate = (AVRational){25, 1}; av_log(NULL, AV_LOG_WARNING, @@ -3497,13 +3389,16 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) switch (enc_ctx->codec_type) { case AVMEDIA_TYPE_AUDIO: enc_ctx->sample_fmt = av_buffersink_get_format(ost->filter->filter); - if (dec_ctx) - enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, - av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); 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); + if (ost->bits_per_raw_sample) + enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; + else if (dec_ctx && ost->filter->graph->is_meta) + enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, + av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3); + init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate)); break; @@ -3526,7 +3421,10 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) av_buffersink_get_sample_aspect_ratio(ost->filter->filter); enc_ctx->pix_fmt = av_buffersink_get_format(ost->filter->filter); - if (dec_ctx) + + if (ost->bits_per_raw_sample) + enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample; + else if (dec_ctx && ost->filter->graph->is_meta) enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample, av_pix_fmt_desc_get(enc_ctx->pix_fmt)->comp[0].depth); @@ -3542,13 +3440,6 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame) ost->st->avg_frame_rate = ost->frame_rate; - if (!dec_ctx || - enc_ctx->width != dec_ctx->width || - enc_ctx->height != dec_ctx->height || - enc_ctx->pix_fmt != dec_ctx->pix_fmt) { - enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample; - } - // Field order: autodetection if (frame) { if (enc_ctx->flags & (AV_CODEC_FLAG_INTERLACED_DCT | AV_CODEC_FLAG_INTERLACED_ME) && @@ -3739,40 +3630,6 @@ static int init_output_stream(OutputStream *ost, AVFrame *frame, return ret; } - // parse user provided disposition, and update stream values - if (ost->disposition) { - static const AVOption opts[] = { - { "disposition" , NULL, 0, AV_OPT_TYPE_FLAGS, { .i64 = 0 }, INT64_MIN, INT64_MAX, .unit = "flags" }, - { "default" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEFAULT }, .unit = "flags" }, - { "dub" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DUB }, .unit = "flags" }, - { "original" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ORIGINAL }, .unit = "flags" }, - { "comment" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_COMMENT }, .unit = "flags" }, - { "lyrics" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_LYRICS }, .unit = "flags" }, - { "karaoke" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_KARAOKE }, .unit = "flags" }, - { "forced" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_FORCED }, .unit = "flags" }, - { "hearing_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_HEARING_IMPAIRED }, .unit = "flags" }, - { "visual_impaired" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_VISUAL_IMPAIRED }, .unit = "flags" }, - { "clean_effects" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CLEAN_EFFECTS }, .unit = "flags" }, - { "attached_pic" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_ATTACHED_PIC }, .unit = "flags" }, - { "captions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, .unit = "flags" }, - { "descriptions" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, .unit = "flags" }, - { "dependent" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DEPENDENT }, .unit = "flags" }, - { "metadata" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, .unit = "flags" }, - { NULL }, - }; - static const AVClass class = { - .class_name = "", - .item_name = av_default_item_name, - .option = opts, - .version = LIBAVUTIL_VERSION_INT, - }; - const AVClass *pclass = &class; - - ret = av_opt_eval_flags(&pclass, &opts[0], ost->disposition, &ost->st->disposition); - if (ret < 0) - return ret; - } - /* initialize bitstream filters for the output stream * needs to be done here, because the codec id for streamcopy is not * known until now */ @@ -4144,8 +4001,10 @@ static int check_keyboard_interaction(int64_t cur_time) last_time = cur_time; }else key = -1; - if (key == 'q') + if (key == 'q') { + av_log(NULL, AV_LOG_INFO, "\n\n[q] command received. Exiting.\n\n"); return AVERROR_EXIT; + } if (key == '+') av_log_set_level(av_log_get_level()+10); if (key == '-') av_log_set_level(av_log_get_level()-10); if (key == 's') qp_hist ^= 1; @@ -5008,7 +4867,7 @@ static int transcode(void) term_exit(); - /* write the trailer if needed and close file */ + /* write the trailer if needed */ for (i = 0; i < nb_output_files; i++) { os = output_files[i]->ctx; if (!output_files[i]->header_written) { @@ -5028,6 +4887,18 @@ static int transcode(void) /* dump report by using the first video and audio streams */ print_report(1, timer_start, av_gettime_relative()); + /* close the output files */ + for (i = 0; i < nb_output_files; i++) { + os = output_files[i]->ctx; + if (os && os->oformat && !(os->oformat->flags & AVFMT_NOFILE)) { + if ((ret = avio_closep(&os->pb)) < 0) { + av_log(NULL, AV_LOG_ERROR, "Error closing file %s: %s\n", os->url, av_err2str(ret)); + if (exit_on_error) + exit_program(1); + } + } + } + /* close each encoder */ for (i = 0; i < nb_output_streams; i++) { ost = output_streams[i]; diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h index 30225e9ffe..9b200b806a 100644 --- a/fftools/ffmpeg.h +++ b/fftools/ffmpeg.h @@ -47,12 +47,14 @@ #include "libswresample/swresample.h" -#define VSYNC_AUTO -1 -#define VSYNC_PASSTHROUGH 0 -#define VSYNC_CFR 1 -#define VSYNC_VFR 2 -#define VSYNC_VSCFR 0xfe -#define VSYNC_DROP 0xff +enum VideoSyncMethod { + VSYNC_AUTO = -1, + VSYNC_PASSTHROUGH, + VSYNC_CFR, + VSYNC_VFR, + VSYNC_VSCFR, + VSYNC_DROP, +}; #define MAX_STREAMS 1024 /* arbitrary sanity check value */ @@ -60,16 +62,8 @@ enum HWAccelID { HWACCEL_NONE = 0, HWACCEL_AUTO, HWACCEL_GENERIC, - HWACCEL_VIDEOTOOLBOX, }; -typedef struct HWAccel { - const char *name; - int (*init)(AVCodecContext *s); - enum HWAccelID id; - enum AVPixelFormat pix_fmt; -} HWAccel; - typedef struct HWDevice { const char *name; enum AVHWDeviceType type; @@ -236,6 +230,8 @@ typedef struct OptionsContext { int nb_enc_time_bases; SpecifierOpt *autoscale; int nb_autoscale; + SpecifierOpt *bits_per_raw_sample; + int nb_bits_per_raw_sample; } OptionsContext; typedef struct InputFilter { @@ -281,9 +277,10 @@ typedef struct OutputFilter { uint64_t channel_layout; // those are only set if no format is specified and the encoder gives us multiple options - int *formats; - uint64_t *channel_layouts; - int *sample_rates; + // They point directly to the relevant lists of the encoder. + const int *formats; + const uint64_t *channel_layouts; + const int *sample_rates; } OutputFilter; typedef struct FilterGraph { @@ -292,6 +289,9 @@ typedef struct FilterGraph { AVFilterGraph *graph; int reconfiguration; + // true when the filtergraph contains only meta filters + // that do not modify the frame data + int is_meta; InputFilter **inputs; int nb_inputs; @@ -311,9 +311,9 @@ typedef struct InputStream { AVCodecContext *dec_ctx; const AVCodec *dec; AVFrame *decoded_frame; - AVFrame *filter_frame; /* a ref of decoded_frame, to be sent to filters */ AVPacket *pkt; + int64_t prev_pkt_pts; int64_t start; /* time when read started */ /* predicted dts of the next packet read for this stream or (when there are * several frames in a packet) of the next frame in current packet (in AV_TIME_BASE units) */ @@ -377,11 +377,9 @@ typedef struct InputStream { /* hwaccel context */ void *hwaccel_ctx; void (*hwaccel_uninit)(AVCodecContext *s); - int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags); int (*hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame); enum AVPixelFormat hwaccel_pix_fmt; enum AVPixelFormat hwaccel_retrieved_pix_fmt; - AVBufferRef *hw_frames_ctx; /* stats */ // combined size of all the packets read @@ -487,11 +485,13 @@ typedef struct OutputStream { /* video only */ AVRational frame_rate; AVRational max_frame_rate; + enum VideoSyncMethod vsync_method; int is_cfr; int force_fps; int top_field_first; int rotate_overridden; int autoscale; + int bits_per_raw_sample; double rotate_override_value; AVRational frame_aspect_ratio; @@ -608,7 +608,7 @@ extern float dts_error_threshold; extern int audio_volume; extern int audio_sync_method; -extern int video_sync_method; +extern enum VideoSyncMethod video_sync_method; extern float frame_drop_threshold; extern int do_benchmark; extern int do_benchmark_all; @@ -628,7 +628,6 @@ extern int stdin_interaction; extern int frame_bits_per_raw_sample; extern AVIOContext *progress_avio; extern float max_error_rate; -extern char *videotoolbox_pixfmt; extern char *filter_nbthreads; extern int filter_complex_nbthreads; @@ -638,7 +637,6 @@ extern int auto_conversion_filters; extern const AVIOInterruptCB int_cb; extern const OptionDef options[]; -extern const HWAccel hwaccels[]; #if CONFIG_QSV extern char *qsv_device; #endif diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c index b798459946..1f6cba2c04 100644 --- a/fftools/ffmpeg_filter.c +++ b/fftools/ffmpeg_filter.c @@ -83,10 +83,13 @@ static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext *enc_ctx return target; } -static char *choose_pix_fmts(OutputFilter *ofilter) +/* May return NULL (no pixel format found), a static string or a string + * backed by the bprint. Nothing has been written to the AVBPrint in case + * NULL is returned. The AVBPrint provided should be clean. */ +static const char *choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint) { OutputStream *ost = ofilter->ost; - AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); + const AVDictionaryEntry *strict_dict = av_dict_get(ost->encoder_opts, "strict", NULL, 0); if (strict_dict) // used by choose_pixel_fmt() and below av_opt_set(ost->enc_ctx, "strict", strict_dict->value, 0); @@ -96,18 +99,12 @@ static char *choose_pix_fmts(OutputFilter *ofilter) AVFILTER_AUTO_CONVERT_NONE); if (ost->enc_ctx->pix_fmt == AV_PIX_FMT_NONE) return NULL; - return av_strdup(av_get_pix_fmt_name(ost->enc_ctx->pix_fmt)); + return av_get_pix_fmt_name(ost->enc_ctx->pix_fmt); } if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { - return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt))); + return av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc_ctx, ost->enc, ost->enc_ctx->pix_fmt)); } else if (ost->enc && ost->enc->pix_fmts) { const enum AVPixelFormat *p; - AVIOContext *s = NULL; - uint8_t *ret; - int len; - - if (avio_open_dyn_buf(&s) < 0) - exit_program(1); p = ost->enc->pix_fmts; if (ost->enc_ctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { @@ -116,11 +113,11 @@ static char *choose_pix_fmts(OutputFilter *ofilter) for (; *p != AV_PIX_FMT_NONE; p++) { const char *name = av_get_pix_fmt_name(*p); - avio_printf(s, "%s|", name); + av_bprintf(bprint, "%s%c", name, p[1] == AV_PIX_FMT_NONE ? '\0' : '|'); } - len = avio_close_dyn_buf(s, &ret); - ret[len - 1] = 0; - return ret; + if (!av_bprint_is_complete(bprint)) + exit_program(1); + return bprint->str; } else return NULL; } @@ -162,33 +159,31 @@ DEF_CHOOSE_FORMAT(channel_layouts, uint64_t, channel_layout, channel_layouts, 0, int init_simple_filtergraph(InputStream *ist, OutputStream *ost) { FilterGraph *fg = av_mallocz(sizeof(*fg)); + OutputFilter *ofilter; + InputFilter *ifilter; if (!fg) exit_program(1); fg->index = nb_filtergraphs; - GROW_ARRAY(fg->outputs, fg->nb_outputs); - if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0])))) - exit_program(1); - fg->outputs[0]->ost = ost; - fg->outputs[0]->graph = fg; - fg->outputs[0]->format = -1; + ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); + ofilter->ost = ost; + ofilter->graph = fg; + ofilter->format = -1; - ost->filter = fg->outputs[0]; + ost->filter = ofilter; - GROW_ARRAY(fg->inputs, fg->nb_inputs); - if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0])))) - exit_program(1); - fg->inputs[0]->ist = ist; - fg->inputs[0]->graph = fg; - fg->inputs[0]->format = -1; + ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); + ifilter->ist = ist; + ifilter->graph = fg; + ifilter->format = -1; - fg->inputs[0]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); - if (!fg->inputs[0]->frame_queue) + ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!ifilter->frame_queue) exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = fg->inputs[0]; + ist->filters[ist->nb_filters - 1] = ifilter; GROW_ARRAY(filtergraphs, nb_filtergraphs); filtergraphs[nb_filtergraphs - 1] = fg; @@ -201,17 +196,15 @@ static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) AVFilterContext *ctx = inout->filter_ctx; AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; - AVIOContext *pb; - uint8_t *res = NULL; + char *res; - if (avio_open_dyn_buf(&pb) < 0) - exit_program(1); - - avio_printf(pb, "%s", ctx->filter->name); if (nb_pads > 1) - avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx)); - avio_w8(pb, 0); - avio_close_dyn_buf(pb, &res); + res = av_strdup(ctx->filter->name); + else + res = av_asprintf("%s:%s", ctx->filter->name, + avfilter_pad_get_name(pads, inout->pad_idx)); + if (!res) + exit_program(1); return res; } @@ -219,6 +212,7 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) { InputStream *ist = NULL; enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx); + InputFilter *ifilter; int i; // TODO: support other filter types @@ -285,21 +279,19 @@ static void init_input_filter(FilterGraph *fg, AVFilterInOut *in) ist->decoding_needed |= DECODING_FOR_FILTER; ist->st->discard = AVDISCARD_NONE; - GROW_ARRAY(fg->inputs, fg->nb_inputs); - if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0])))) - exit_program(1); - fg->inputs[fg->nb_inputs - 1]->ist = ist; - fg->inputs[fg->nb_inputs - 1]->graph = fg; - fg->inputs[fg->nb_inputs - 1]->format = -1; - fg->inputs[fg->nb_inputs - 1]->type = ist->st->codecpar->codec_type; - fg->inputs[fg->nb_inputs - 1]->name = describe_filter_link(fg, in, 1); + ifilter = ALLOC_ARRAY_ELEM(fg->inputs, fg->nb_inputs); + ifilter->ist = ist; + ifilter->graph = fg; + ifilter->format = -1; + ifilter->type = ist->st->codecpar->codec_type; + ifilter->name = describe_filter_link(fg, in, 1); - fg->inputs[fg->nb_inputs - 1]->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); - if (!fg->inputs[fg->nb_inputs - 1]->frame_queue) + ifilter->frame_queue = av_fifo_alloc(8 * sizeof(AVFrame*)); + if (!ifilter->frame_queue) exit_program(1); GROW_ARRAY(ist->filters, ist->nb_filters); - ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1]; + ist->filters[ist->nb_filters - 1] = ifilter; } int init_complex_filtergraph(FilterGraph *fg) @@ -323,18 +315,15 @@ int init_complex_filtergraph(FilterGraph *fg) init_input_filter(fg, cur); for (cur = outputs; cur;) { - GROW_ARRAY(fg->outputs, fg->nb_outputs); - fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0])); - if (!fg->outputs[fg->nb_outputs - 1]) - exit_program(1); + OutputFilter *const ofilter = ALLOC_ARRAY_ELEM(fg->outputs, fg->nb_outputs); - fg->outputs[fg->nb_outputs - 1]->graph = fg; - fg->outputs[fg->nb_outputs - 1]->out_tmp = cur; - fg->outputs[fg->nb_outputs - 1]->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, + ofilter->graph = fg; + ofilter->out_tmp = cur; + ofilter->type = avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx); - fg->outputs[fg->nb_outputs - 1]->name = describe_filter_link(fg, cur, 0); + ofilter->name = describe_filter_link(fg, cur, 0); cur = cur->next; - fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL; + ofilter->out_tmp->next = NULL; } fail: @@ -418,12 +407,13 @@ static int insert_filter(AVFilterContext **last_filter, int *pad_idx, static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out) { - char *pix_fmts; OutputStream *ost = ofilter->ost; OutputFile *of = output_files[ost->file_index]; AVFilterContext *last_filter = out->filter_ctx; + AVBPrint bprint; int pad_idx = out->pad_idx; int ret; + const char *pix_fmts; char name[255]; snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); @@ -437,7 +427,7 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, if ((ofilter->width || ofilter->height) && ofilter->ost->autoscale) { char args[255]; AVFilterContext *filter; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; snprintf(args, sizeof(args), "%d:%d", ofilter->width, ofilter->height); @@ -459,13 +449,14 @@ static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, pad_idx = 0; } - if ((pix_fmts = choose_pix_fmts(ofilter))) { + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + if ((pix_fmts = choose_pix_fmts(ofilter, &bprint))) { AVFilterContext *filter; ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("format"), "format", pix_fmts, NULL, fg->graph); - av_freep(&pix_fmts); + av_bprint_finalize(&bprint, NULL); if (ret < 0) return ret; if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) @@ -770,12 +761,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, theta = get_rotation(displaymatrix); if (fabs(theta - 90) < 1.0) { - if (displaymatrix[3] > 0) { - ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); - if (ret < 0) - return ret; - } - ret = insert_filter(&last_filter, &pad_idx, "transpose", "clock"); + ret = insert_filter(&last_filter, &pad_idx, "transpose", + displaymatrix[3] > 0 ? "cclock_flip" : "clock"); } else if (fabs(theta - 180) < 1.0) { if (displaymatrix[0] < 0) { ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); @@ -786,12 +773,8 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); } } else if (fabs(theta - 270) < 1.0) { - if (displaymatrix[3] < 0) { - ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); - if (ret < 0) - return ret; - } - ret = insert_filter(&last_filter, &pad_idx, "transpose", "cclock"); + ret = insert_filter(&last_filter, &pad_idx, "transpose", + displaymatrix[3] < 0 ? "clock_flip" : "cclock"); } else if (fabs(theta) > 1.0) { char rotate_buf[64]; snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta); @@ -805,23 +788,6 @@ static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter, return ret; } - if (do_deinterlace) { - AVFilterContext *yadif; - - snprintf(name, sizeof(name), "deinterlace_in_%d_%d", - ist->file_index, ist->st->index); - if ((ret = avfilter_graph_create_filter(&yadif, - avfilter_get_by_name("yadif"), - name, "", NULL, - fg->graph)) < 0) - return ret; - - if ((ret = avfilter_link(last_filter, 0, yadif, 0)) < 0) - return ret; - - last_filter = yadif; - } - snprintf(name, sizeof(name), "trim_in_%d_%d", ist->file_index, ist->st->index); if (copy_ts) { @@ -980,6 +946,30 @@ static void cleanup_filtergraph(FilterGraph *fg) avfilter_graph_free(&fg->graph); } +static int filter_is_buffersrc(const AVFilterContext *f) +{ + return f->nb_inputs == 0 && + (!strcmp(f->filter->name, "buffersrc") || + !strcmp(f->filter->name, "abuffersrc")); +} + +static int graph_is_meta(AVFilterGraph *graph) +{ + for (unsigned i = 0; i < graph->nb_filters; i++) { + const AVFilterContext *f = graph->filters[i]; + + /* in addition to filters flagged as meta, also + * disregard sinks and buffersources (but not other sources, + * since they introduce data we are not aware of) + */ + if (!((f->filter->flags & AVFILTER_FLAG_METADATA_ONLY) || + f->nb_outputs == 0 || + filter_is_buffersrc(f))) + return 0; + } + return 1; +} + int configure_filtergraph(FilterGraph *fg) { AVFilterInOut *inputs, *outputs, *cur; @@ -994,7 +984,7 @@ int configure_filtergraph(FilterGraph *fg) if (simple) { OutputStream *ost = fg->outputs[0]->ost; char args[512]; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; if (filter_nbthreads) { ret = av_opt_set(fg->graph, "threads", filter_nbthreads, 0); @@ -1080,6 +1070,8 @@ int configure_filtergraph(FilterGraph *fg) if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0) goto fail; + fg->is_meta = graph_is_meta(fg->graph); + /* limit the lists of allowed formats to the ones selected, to * make sure they stay the same if the filtergraph is reconfigured later */ for (i = 0; i < fg->nb_outputs; i++) { diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 48429bc3aa..cec7163de8 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -38,6 +38,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/avutil.h" +#include "libavutil/bprint.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/fifo.h" @@ -83,7 +84,7 @@ static const char *const opt_name_inter_matrices[] = {"inter_matrix", static const char *const opt_name_chroma_intra_matrices[] = {"chroma_intra_matrix", NULL}; static const char *const opt_name_top_field_first[] = {"top", NULL}; static const char *const opt_name_presets[] = {"pre", "apre", "vpre", "spre", NULL}; -static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkfr", NULL}; +static const char *const opt_name_copy_initial_nonkeyframes[] = {"copyinkf", NULL}; static const char *const opt_name_copy_prior_start[] = {"copypriorss", NULL}; static const char *const opt_name_filters[] = {"filter", "af", "vf", NULL}; static const char *const opt_name_filter_scripts[] = {"filter_script", NULL}; @@ -100,6 +101,7 @@ static const char *const opt_name_discard[] = {"discard", NULL static const char *const opt_name_disposition[] = {"disposition", NULL}; static const char *const opt_name_time_bases[] = {"time_base", NULL}; static const char *const opt_name_enc_time_bases[] = {"enc_time_base", NULL}; +static const char *const opt_name_bits_per_raw_sample[] = {"bits_per_raw_sample", NULL}; #define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\ {\ @@ -138,12 +140,6 @@ static const char *const opt_name_enc_time_bases[] = {"enc_time_base" }\ } -const HWAccel hwaccels[] = { -#if CONFIG_VIDEOTOOLBOX - { "videotoolbox", videotoolbox_init, HWACCEL_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX }, -#endif - { 0 }, -}; HWDevice *filter_hw_device; char *vstats_filename; @@ -155,9 +151,8 @@ float dts_error_threshold = 3600*30; int audio_volume = 256; int audio_sync_method = 0; -int video_sync_method = VSYNC_AUTO; +enum VideoSyncMethod video_sync_method = VSYNC_AUTO; float frame_drop_threshold = 0; -int do_deinterlace = 0; int do_benchmark = 0; int do_benchmark_all = 0; int do_hex_dump = 0; @@ -171,7 +166,6 @@ int abort_on_flags = 0; int print_stats = -1; int qp_hist = 0; int stdin_interaction = 1; -int frame_bits_per_raw_sample = 0; float max_error_rate = 2.0/3; char *filter_nbthreads; int filter_complex_nbthreads = 0; @@ -180,11 +174,9 @@ int auto_conversion_filters = 1; int64_t stats_period = 500000; -static int intra_only = 0; static int file_overwrite = 0; static int no_file_overwrite = 0; static int do_psnr = 0; -static int input_sync; static int input_stream_potentially_available = 0; static int ignore_unknown_streams = 0; static int copy_unknown_streams = 0; @@ -253,7 +245,7 @@ static int show_hwaccels(void *optctx, const char *opt, const char *arg) /* return a copy of the input with the stream specifiers removed from the keys */ static AVDictionary *strip_specifiers(AVDictionary *dict) { - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; AVDictionary *ret = NULL; while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX))) { @@ -309,27 +301,6 @@ static int opt_stats_period(void *optctx, const char *opt, const char *arg) return 0; } -static int opt_sameq(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_ERROR, "Option '%s' was removed. " - "If you are looking for an option to preserve the quality (which is not " - "what -%s was for), use -qscale 0 or an equivalent quality factor option.\n", - opt, opt); - return AVERROR(EINVAL); -} - -static int opt_video_channel(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -channel.\n"); - return opt_default(optctx, "channel", arg); -} - -static int opt_video_standard(void *optctx, const char *opt, const char *arg) -{ - av_log(NULL, AV_LOG_WARNING, "This option is deprecated, use -standard.\n"); - return opt_default(optctx, "standard", arg); -} - static int opt_audio_codec(void *optctx, const char *opt, const char *arg) { OptionsContext *o = optctx; @@ -890,6 +861,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) } ist->filter_in_rescale_delta_last = AV_NOPTS_VALUE; + ist->prev_pkt_pts = AV_NOPTS_VALUE; ist->dec_ctx = avcodec_alloc_context3(ist->dec); if (!ist->dec_ctx) { @@ -903,6 +875,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) exit_program(1); } + ist->decoded_frame = av_frame_alloc(); + if (!ist->decoded_frame) + exit_program(1); + ist->pkt = av_packet_alloc(); if (!ist->pkt) exit_program(1); @@ -965,21 +941,10 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) else if (!strcmp(hwaccel, "auto")) ist->hwaccel_id = HWACCEL_AUTO; else { - enum AVHWDeviceType type; - int i; - for (i = 0; hwaccels[i].name; i++) { - if (!strcmp(hwaccels[i].name, hwaccel)) { - ist->hwaccel_id = hwaccels[i].id; - break; - } - } - - if (!ist->hwaccel_id) { - type = av_hwdevice_find_type_by_name(hwaccel); - if (type != AV_HWDEVICE_TYPE_NONE) { - ist->hwaccel_id = HWACCEL_GENERIC; - ist->hwaccel_device_type = type; - } + enum AVHWDeviceType type = av_hwdevice_find_type_by_name(hwaccel); + if (type != AV_HWDEVICE_TYPE_NONE) { + ist->hwaccel_id = HWACCEL_GENERIC; + ist->hwaccel_device_type = type; } if (!ist->hwaccel_id) { @@ -1088,7 +1053,7 @@ static void dump_attachment(AVStream *st, const char *filename) { int ret; AVIOContext *out = NULL; - AVDictionaryEntry *e; + const AVDictionaryEntry *e; if (!st->codecpar->extradata_size) { av_log(NULL, AV_LOG_WARNING, "No extradata to dump in stream #%d:%d.\n", @@ -1124,7 +1089,7 @@ static int open_input_file(OptionsContext *o, const char *filename) int err, i, ret; int64_t timestamp; AVDictionary *unused_opts = NULL; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; char * video_codec_name = NULL; char * audio_codec_name = NULL; char *subtitle_codec_name = NULL; @@ -1316,11 +1281,7 @@ static int open_input_file(OptionsContext *o, const char *filename) /* dump the file content */ av_dump_format(ic, nb_input_files, filename, 0); - GROW_ARRAY(input_files, nb_input_files); - f = av_mallocz(sizeof(*f)); - if (!f) - exit_program(1); - input_files[nb_input_files - 1] = f; + f = ALLOC_ARRAY_ELEM(input_files, nb_input_files); f->ctx = ic; f->ist_index = nb_input_streams - ic->nb_streams; @@ -1406,23 +1367,18 @@ static int open_input_file(OptionsContext *o, const char *filename) return 0; } -static uint8_t *get_line(AVIOContext *s) +static char *get_line(AVIOContext *s, AVBPrint *bprint) { - AVIOContext *line; - uint8_t *buf; char c; - if (avio_open_dyn_buf(&line) < 0) { + while ((c = avio_r8(s)) && c != '\n') + av_bprint_chars(bprint, c, 1); + + if (!av_bprint_is_complete(bprint)) { av_log(NULL, AV_LOG_FATAL, "Could not alloc buffer for reading preset.\n"); exit_program(1); } - - while ((c = avio_r8(s)) && c != '\n') - avio_w8(line, c); - avio_w8(line, 0); - avio_close_dyn_buf(line, &buf); - - return buf; + return bprint->str; } static int get_preset_file_2(const char *preset_name, const char *codec_name, AVIOContext **s) @@ -1535,6 +1491,10 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e exit_program(1); } + ost->filtered_frame = av_frame_alloc(); + if (!ost->filtered_frame) + exit_program(1); + ost->pkt = av_packet_alloc(); if (!ost->pkt) exit_program(1); @@ -1549,20 +1509,21 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->autoscale = 1; MATCH_PER_STREAM_OPT(autoscale, i, ost->autoscale, oc, st); if (preset && (!(ret = get_preset_file_2(preset, ost->enc->name, &s)))) { + AVBPrint bprint; + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); do { - buf = get_line(s); - if (!buf[0] || buf[0] == '#') { - av_free(buf); + av_bprint_clear(&bprint); + buf = get_line(s, &bprint); + if (!buf[0] || buf[0] == '#') continue; - } if (!(arg = strchr(buf, '='))) { av_log(NULL, AV_LOG_FATAL, "Invalid line found in the preset file.\n"); exit_program(1); } *arg++ = 0; av_dict_set(&ost->encoder_opts, buf, arg, AV_DICT_DONT_OVERWRITE); - av_free(buf); } while (!s->eof_reached); + av_bprint_finalize(&bprint, NULL); avio_closep(&s); } if (ret) { @@ -1643,6 +1604,7 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->max_muxing_queue_size = 1024; 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; @@ -1650,6 +1612,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e ost->muxing_queue_data_threshold = 50*1024*1024; MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st); + MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample, + oc, st); + if (oc->oformat->flags & AVFMT_GLOBALHEADER) ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; @@ -1692,29 +1657,26 @@ static void parse_matrix_coeffs(uint16_t *dest, const char *str) } /* read file contents into a string */ -static uint8_t *read_file(const char *filename) +static char *read_file(const char *filename) { AVIOContext *pb = NULL; - AVIOContext *dyn_buf = NULL; int ret = avio_open(&pb, filename, AVIO_FLAG_READ); - uint8_t buf[1024], *str; + AVBPrint bprint; + char *str; if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error opening file %s.\n", filename); return NULL; } - ret = avio_open_dyn_buf(&dyn_buf); + av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); + ret = avio_read_to_bprint(pb, &bprint, SIZE_MAX); + avio_closep(&pb); if (ret < 0) { - avio_closep(&pb); + av_bprint_finalize(&bprint, NULL); return NULL; } - while ((ret = avio_read(pb, buf, sizeof(buf))) > 0) - avio_write(dyn_buf, buf, ret); - avio_w8(dyn_buf, 0); - avio_closep(&pb); - - ret = avio_close_dyn_buf(dyn_buf, &str); + ret = av_bprint_finalize(&bprint, &str); if (ret < 0) return NULL; return str; @@ -1784,7 +1746,7 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in if ((frame_rate || max_frame_rate) && video_sync_method == VSYNC_PASSTHROUGH) - av_log(NULL, AV_LOG_ERROR, "Using -vsync 0 and -r/-fpsmax can produce invalid output files\n"); + av_log(NULL, AV_LOG_ERROR, "Using -vsync passthrough and -r/-fpsmax can produce invalid output files\n"); MATCH_PER_STREAM_OPT(frame_aspect_ratios, str, frame_aspect_ratio, oc, st); if (frame_aspect_ratio) { @@ -1815,7 +1777,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in exit_program(1); } - video_enc->bits_per_raw_sample = frame_bits_per_raw_sample; MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st); if (frame_pix_fmt && *frame_pix_fmt == '+') { ost->keep_pix_fmt = 1; @@ -1828,8 +1789,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in } st->sample_aspect_ratio = video_enc->sample_aspect_ratio; - if (intra_only) - video_enc->gop_size = 0; MATCH_PER_STREAM_OPT(intra_matrices, str, intra_matrix, oc, st); if (intra_matrix) { if (!(video_enc->intra_matrix = av_mallocz(sizeof(*video_enc->intra_matrix) * 64))) { @@ -1951,10 +1910,38 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in ost->top_field_first = -1; MATCH_PER_STREAM_OPT(top_field_first, i, ost->top_field_first, oc, st); + ost->vsync_method = video_sync_method; + if (ost->vsync_method == VSYNC_AUTO) { + if (!strcmp(oc->oformat->name, "avi")) { + ost->vsync_method = VSYNC_VFR; + } else { + ost->vsync_method = (oc->oformat->flags & AVFMT_VARIABLE_FPS) ? + ((oc->oformat->flags & AVFMT_NOTIMESTAMPS) ? + VSYNC_PASSTHROUGH : VSYNC_VFR) : + VSYNC_CFR; + } + + if (ost->source_index >= 0 && ost->vsync_method == VSYNC_CFR) { + const InputStream *ist = input_streams[ost->source_index]; + const InputFile *ifile = input_files[ist->file_index]; + + if (ifile->nb_streams == 1 && ifile->input_ts_offset == 0) + ost->vsync_method = VSYNC_VSCFR; + } + + if (ost->vsync_method == VSYNC_CFR && copy_ts) { + ost->vsync_method = VSYNC_VSCFR; + } + } + ost->is_cfr = (ost->vsync_method == VSYNC_CFR || ost->vsync_method == VSYNC_VSCFR); ost->avfilter = get_ost_filters(o, oc, ost); if (!ost->avfilter) exit_program(1); + + 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); } @@ -2165,6 +2152,72 @@ static int copy_chapters(InputFile *ifile, OutputFile *ofile, int copy_metadata) return 0; } +static int set_dispositions(OutputFile *of) +{ + 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++) { + OutputStream *ost = output_streams[of->ost_index + i]; + + nb_streams[ost->st->codecpar->codec_type]++; + + have_manual |= !!ost->disposition; + + if (ost->source_index >= 0) { + ost->st->disposition = input_streams[ost->source_index]->st->disposition; + + if (ost->st->disposition & AV_DISPOSITION_DEFAULT) + have_default[ost->st->codecpar->codec_type] = 1; + } + } + + if (have_manual) { + // process manually set dispositions - they override the above copy + for (int i = 0; i< of->ctx->nb_streams; i++) { + OutputStream *ost = output_streams[of->ost_index + i]; + int ret; + + if (!ost->disposition) + continue; + +#if LIBAVFORMAT_VERSION_MAJOR >= 60 + ret = av_opt_set(ost->st, "disposition", ost->disposition, 0); +#else + { + const AVClass *class = av_stream_get_class(); + const AVOption *o = av_opt_find(&class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + + av_assert0(o); + ret = av_opt_eval_flags(&class, o, ost->disposition, &ost->st->disposition); + } +#endif + + if (ret < 0) + return ret; + } + } else { + // 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++) { + OutputStream *ost = output_streams[of->ost_index + i]; + enum AVMediaType type = ost->st->codecpar->codec_type; + + if (nb_streams[type] < 2 || have_default[type] || + ost->st->disposition & AV_DISPOSITION_ATTACHED_PIC) + continue; + + ost->st->disposition |= AV_DISPOSITION_DEFAULT; + have_default[type] = 1; + } + } + + return 0; +} + static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, AVFormatContext *oc) { @@ -2179,7 +2232,6 @@ static void init_output_filter(OutputFilter *ofilter, OptionsContext *o, exit_program(1); } - ost->source_index = -1; ost->filter = ofilter; ofilter->ost = ost; @@ -2260,7 +2312,7 @@ static int open_output_file(OptionsContext *o, const char *filename) OutputStream *ost; InputStream *ist; AVDictionary *unused_opts = NULL; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; if (o->stop_time != INT64_MAX && o->recording_time != INT64_MAX) { o->stop_time = INT64_MAX; @@ -2277,11 +2329,7 @@ static int open_output_file(OptionsContext *o, const char *filename) } } - GROW_ARRAY(output_files, nb_output_files); - of = av_mallocz(sizeof(*of)); - if (!of) - exit_program(1); - output_files[nb_output_files - 1] = of; + of = ALLOC_ARRAY_ELEM(output_files, nb_output_files); of->ost_index = nb_output_streams; of->recording_time = o->recording_time; @@ -2629,7 +2677,6 @@ loop_end: /* set the filter output constraints */ if (ost->filter) { OutputFilter *f = ost->filter; - int count; switch (ost->enc_ctx->codec_type) { case AVMEDIA_TYPE_VIDEO: f->frame_rate = ost->frame_rate; @@ -2637,51 +2684,25 @@ loop_end: f->height = ost->enc_ctx->height; if (ost->enc_ctx->pix_fmt != AV_PIX_FMT_NONE) { f->format = ost->enc_ctx->pix_fmt; - } else if (ost->enc->pix_fmts) { - count = 0; - while (ost->enc->pix_fmts[count] != AV_PIX_FMT_NONE) - count++; - f->formats = av_calloc(count + 1, sizeof(*f->formats)); - if (!f->formats) - exit_program(1); - memcpy(f->formats, ost->enc->pix_fmts, (count + 1) * sizeof(*f->formats)); + } else { + f->formats = ost->enc->pix_fmts; } break; case AVMEDIA_TYPE_AUDIO: if (ost->enc_ctx->sample_fmt != AV_SAMPLE_FMT_NONE) { f->format = ost->enc_ctx->sample_fmt; - } else if (ost->enc->sample_fmts) { - count = 0; - while (ost->enc->sample_fmts[count] != AV_SAMPLE_FMT_NONE) - count++; - f->formats = av_calloc(count + 1, sizeof(*f->formats)); - if (!f->formats) - exit_program(1); - memcpy(f->formats, ost->enc->sample_fmts, (count + 1) * sizeof(*f->formats)); + } else { + f->formats = ost->enc->sample_fmts; } if (ost->enc_ctx->sample_rate) { f->sample_rate = ost->enc_ctx->sample_rate; - } else if (ost->enc->supported_samplerates) { - count = 0; - while (ost->enc->supported_samplerates[count]) - count++; - f->sample_rates = av_calloc(count + 1, sizeof(*f->sample_rates)); - if (!f->sample_rates) - exit_program(1); - memcpy(f->sample_rates, ost->enc->supported_samplerates, - (count + 1) * sizeof(*f->sample_rates)); + } 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 if (ost->enc->channel_layouts) { - count = 0; - while (ost->enc->channel_layouts[count]) - count++; - f->channel_layouts = av_calloc(count + 1, sizeof(*f->channel_layouts)); - if (!f->channel_layouts) - exit_program(1); - memcpy(f->channel_layouts, ost->enc->channel_layouts, - (count + 1) * sizeof(*f->channel_layouts)); + } else { + f->channel_layouts = ost->enc->channel_layouts; } break; } @@ -2926,6 +2947,12 @@ loop_end: } } + err = set_dispositions(of); + if (err < 0) { + av_log(NULL, AV_LOG_FATAL, "Error setting output stream dispositions\n"); + exit_program(1); + } + return 0; } @@ -3257,8 +3284,11 @@ static int opt_vsync(void *optctx, const char *opt, const char *arg) 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) + 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"); + } return 0; } @@ -3320,12 +3350,12 @@ 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) { - GROW_ARRAY(filtergraphs, nb_filtergraphs); - if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) - return AVERROR(ENOMEM); - filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; - filtergraphs[nb_filtergraphs - 1]->graph_desc = av_strdup(arg); - if (!filtergraphs[nb_filtergraphs - 1]->graph_desc) + FilterGraph *fg; + ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); + fg = filtergraphs[nb_filtergraphs - 1]; + fg->index = nb_filtergraphs - 1; + fg->graph_desc = av_strdup(arg); + if (!fg->graph_desc) return AVERROR(ENOMEM); input_stream_potentially_available = 1; @@ -3335,15 +3365,14 @@ static int opt_filter_complex(void *optctx, const char *opt, const char *arg) static int opt_filter_complex_script(void *optctx, const char *opt, const char *arg) { - uint8_t *graph_desc = read_file(arg); + FilterGraph *fg; + char *graph_desc = read_file(arg); if (!graph_desc) return AVERROR(EINVAL); - GROW_ARRAY(filtergraphs, nb_filtergraphs); - if (!(filtergraphs[nb_filtergraphs - 1] = av_mallocz(sizeof(*filtergraphs[0])))) - return AVERROR(ENOMEM); - filtergraphs[nb_filtergraphs - 1]->index = nb_filtergraphs - 1; - filtergraphs[nb_filtergraphs - 1]->graph_desc = graph_desc; + fg = ALLOC_ARRAY_ELEM(filtergraphs, nb_filtergraphs); + fg->index = nb_filtergraphs - 1; + fg->graph_desc = graph_desc; input_stream_potentially_available = 1; @@ -3739,6 +3768,9 @@ const OptionDef options[] = { "set the maximum number of queued packets from the demuxer" }, { "find_stream_info", OPT_BOOL | OPT_PERFILE | OPT_INPUT | OPT_EXPERT, { &find_stream_info }, "read and decode the streams to fill missing information with heuristics" }, + { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, + { .off = OFFSET(bits_per_raw_sample) }, + "set the number of bits per raw sample", "number" }, /* video options */ { "vframes", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_video_frames }, @@ -3758,10 +3790,6 @@ const OptionDef options[] = { { "pix_fmt", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(frame_pix_fmts) }, "set pixel format", "format" }, - { "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG, { &frame_bits_per_raw_sample }, - "set the number of bits per raw sample", "number" }, - { "intra", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &intra_only }, - "deprecated use -g 1" }, { "vn", OPT_VIDEO | OPT_BOOL | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) }, "disable video" }, { "rc_override", OPT_VIDEO | HAS_ARG | OPT_EXPERT | OPT_STRING | OPT_SPEC | @@ -3770,10 +3798,6 @@ const OptionDef options[] = { { "vcodec", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_INPUT | OPT_OUTPUT, { .func_arg = opt_video_codec }, "force video codec ('copy' to copy stream)", "codec" }, - { "sameq", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq }, - "Removed" }, - { "same_quant", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_sameq }, - "Removed" }, { "timecode", OPT_VIDEO | HAS_ARG | OPT_PERFILE | OPT_OUTPUT, { .func_arg = opt_timecode }, "set initial TimeCode value.", "hh:mm:ss[:;.]ff" }, { "pass", OPT_VIDEO | HAS_ARG | OPT_SPEC | OPT_INT | OPT_OUTPUT, { .off = OFFSET(pass) }, @@ -3781,8 +3805,6 @@ const OptionDef options[] = { { "passlogfile", OPT_VIDEO | HAS_ARG | OPT_STRING | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(passlogfiles) }, "select two pass log file name prefix", "prefix" }, - { "deinterlace", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_deinterlace }, - "this option is deprecated, use the yadif filter instead" }, { "psnr", OPT_VIDEO | OPT_BOOL | OPT_EXPERT, { &do_psnr }, "calculate PSNR of compressed frames" }, { "vstats", OPT_VIDEO | OPT_EXPERT , { .func_arg = opt_vstats }, @@ -3832,9 +3854,6 @@ const OptionDef options[] = { { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, "select output format used with HW accelerated decoding", "format" }, -#if CONFIG_VIDEOTOOLBOX - { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, -#endif { "hwaccels", OPT_EXIT, { .func_arg = show_hwaccels }, "show available HW acceleration methods" }, { "autorotate", HAS_ARG | OPT_BOOL | OPT_SPEC | @@ -3888,13 +3907,6 @@ const OptionDef options[] = { { "canvas_size", OPT_SUBTITLE | HAS_ARG | OPT_STRING | OPT_SPEC | OPT_INPUT, { .off = OFFSET(canvas_sizes) }, "set canvas size (WxH or abbreviation)", "size" }, - /* grab options */ - { "vc", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_channel }, - "deprecated, use -channel", "channel" }, - { "tvstd", HAS_ARG | OPT_EXPERT | OPT_VIDEO, { .func_arg = opt_video_standard }, - "deprecated, use -standard", "standard" }, - { "isync", OPT_BOOL | OPT_EXPERT, { &input_sync }, "this option is deprecated and does nothing", "" }, - /* muxer options */ { "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT | OPT_OFFSET | OPT_OUTPUT, { .off = OFFSET(mux_max_delay) }, "set the maximum demux-decode delay", "seconds" }, diff --git a/fftools/ffmpeg_videotoolbox.c b/fftools/ffmpeg_videotoolbox.c deleted file mode 100644 index 4ba8618539..0000000000 --- a/fftools/ffmpeg_videotoolbox.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" - -#if HAVE_UTGETOSTYPEFROMSTRING -#include -#endif - -#include "libavcodec/avcodec.h" -#include "libavcodec/videotoolbox.h" -#include "libavutil/imgutils.h" -#include "ffmpeg.h" - -typedef struct VTContext { - AVFrame *tmp_frame; - int log_once; -} VTContext; - -char *videotoolbox_pixfmt; - -static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame) -{ - InputStream *ist = s->opaque; - VTContext *vt = ist->hwaccel_ctx; - CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3]; - OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf); - CVReturn err; - uint8_t *data[4] = { 0 }; - int linesize[4] = { 0 }; - int planes, ret, i; - - if (frame->format == ist->hwaccel_output_format) { - av_log_once(s, AV_LOG_INFO, AV_LOG_TRACE, &vt->log_once, - "There is no video filter for videotoolbox pix_fmt now, remove the " - "-hwaccel_output_format option if video filter doesn't work\n"); - return 0; - } - - av_frame_unref(vt->tmp_frame); - - switch (pixel_format) { - case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break; - case kCVPixelFormatType_422YpCbCr8: vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break; - case kCVPixelFormatType_32BGRA: vt->tmp_frame->format = AV_PIX_FMT_BGRA; break; -#ifdef kCFCoreFoundationVersionNumber10_7 - case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break; -#endif -#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE - case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break; -#endif - default: - av_log(NULL, AV_LOG_ERROR, - "%s: Unsupported pixel format: %s\n", - av_fourcc2str(s->codec_tag), videotoolbox_pixfmt); - return AVERROR(ENOSYS); - } - - vt->tmp_frame->width = frame->width; - vt->tmp_frame->height = frame->height; - ret = av_frame_get_buffer(vt->tmp_frame, 0); - if (ret < 0) - return ret; - - err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); - if (err != kCVReturnSuccess) { - av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n"); - return AVERROR_UNKNOWN; - } - - if (CVPixelBufferIsPlanar(pixbuf)) { - - planes = CVPixelBufferGetPlaneCount(pixbuf); - for (i = 0; i < planes; i++) { - data[i] = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i); - linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i); - } - } else { - data[0] = CVPixelBufferGetBaseAddress(pixbuf); - linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf); - } - - av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize, - (const uint8_t **)data, linesize, vt->tmp_frame->format, - frame->width, frame->height); - - ret = av_frame_copy_props(vt->tmp_frame, frame); - CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly); - if (ret < 0) - return ret; - - av_frame_unref(frame); - av_frame_move_ref(frame, vt->tmp_frame); - - return 0; -} - -static void videotoolbox_uninit(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - VTContext *vt = ist->hwaccel_ctx; - - ist->hwaccel_uninit = NULL; - ist->hwaccel_retrieve_data = NULL; - - av_frame_free(&vt->tmp_frame); - - av_videotoolbox_default_free(s); - av_freep(&ist->hwaccel_ctx); -} - -int videotoolbox_init(AVCodecContext *s) -{ - InputStream *ist = s->opaque; - int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR; - int ret = 0; - VTContext *vt; - - vt = av_mallocz(sizeof(*vt)); - if (!vt) - return AVERROR(ENOMEM); - - ist->hwaccel_ctx = vt; - ist->hwaccel_uninit = videotoolbox_uninit; - ist->hwaccel_retrieve_data = videotoolbox_retrieve_data; - - vt->tmp_frame = av_frame_alloc(); - if (!vt->tmp_frame) { - ret = AVERROR(ENOMEM); - goto fail; - } - - // TODO: reindent - if (!videotoolbox_pixfmt) { - ret = av_videotoolbox_default_init(s); - } else { - AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context(); - CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault, - videotoolbox_pixfmt, - kCFStringEncodingUTF8); -#if HAVE_UTGETOSTYPEFROMSTRING - vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str); -#else - av_log(s, loglevel, "UTGetOSTypeFromString() is not available " - "on this platform, %s pixel format can not be honored from " - "the command line\n", videotoolbox_pixfmt); -#endif - ret = av_videotoolbox_default_init2(s, vtctx); - CFRelease(pixfmt_str); - } - if (ret < 0) { - av_log(NULL, loglevel, "Error creating Videotoolbox decoder.\n"); - goto fail; - } - - return 0; -fail: - videotoolbox_uninit(s); - return ret; -} diff --git a/fftools/ffplay.c b/fftools/ffplay.c index ccea0e4578..e7b20be76b 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -1856,7 +1856,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c AVFilterContext *filt_src = NULL, *filt_out = NULL, *last_filter = NULL; AVCodecParameters *codecpar = is->video_st->codecpar; AVRational fr = av_guess_frame_rate(is->ic, is->video_st, NULL); - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; int nb_pix_fmts = 0; int i, j; @@ -1960,7 +1960,7 @@ static int configure_audio_filters(VideoState *is, const char *afilters, int for int channels[2] = { 0, -1 }; AVFilterContext *filt_asrc = NULL, *filt_asink = NULL; char aresample_swr_opts[512] = ""; - AVDictionaryEntry *e = NULL; + const AVDictionaryEntry *e = NULL; char asrc_args[256]; int ret; @@ -2575,7 +2575,7 @@ static int stream_component_open(VideoState *is, int stream_index) const AVCodec *codec; const char *forced_codec_name = NULL; AVDictionary *opts = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int sample_rate, nb_channels; int64_t channel_layout; int ret = 0; @@ -2760,7 +2760,7 @@ static int read_thread(void *arg) AVPacket *pkt = NULL; int64_t stream_start_time; int pkt_in_play_range = 0; - AVDictionaryEntry *t; + const AVDictionaryEntry *t; SDL_mutex *wait_mutex = SDL_CreateMutex(); int scan_all_pmts_set = 0; int64_t pkt_ts; @@ -3746,6 +3746,10 @@ int main(int argc, char **argv) flags |= SDL_WINDOW_BORDERLESS; else flags |= SDL_WINDOW_RESIZABLE; + +#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); +#endif window = SDL_CreateWindow(program_name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, default_width, default_height, flags); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); if (window) { diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index 90e895bbf9..20582ca7ac 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -175,6 +175,10 @@ typedef enum { SECTION_ID_FRAME_SIDE_DATA, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_TIMECODE, + SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, + SECTION_ID_FRAME_SIDE_DATA_COMPONENT, + SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, + SECTION_ID_FRAME_SIDE_DATA_PIECE, SECTION_ID_FRAME_LOG, SECTION_ID_FRAME_LOGS, SECTION_ID_LIBRARY_VERSION, @@ -219,9 +223,13 @@ 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, -1 } }, - [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] = { 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_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 } }, + [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", 0, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 } }, + [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "section", 0, { -1 } }, [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } }, [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, }, [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } }, @@ -580,7 +588,7 @@ static int writer_open(WriterContext **wctx, const Writer *writer, const char *a /* convert options to dictionary */ if (args) { AVDictionary *opts = NULL; - AVDictionaryEntry *opt = NULL; + const AVDictionaryEntry *opt = NULL; if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) { av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args); @@ -1151,8 +1159,10 @@ static void compact_print_section_header(WriterContext *wctx) if (parent_section && compact->has_nested_elems[wctx->level-1] && (section->flags & SECTION_FLAG_IS_ARRAY)) { compact->terminate_line[wctx->level-1] = 0; - printf("\n"); } + 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); if (compact->print_section && !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) printf("%s%c", section->name, compact->item_sep); @@ -1807,6 +1817,16 @@ static void writer_register_all(void) writer_print_string(w, k, pbuf.str, 0); \ } while (0) +#define print_list_fmt(k, f, n, ...) do { \ + av_bprint_clear(&pbuf); \ + for (int idx = 0; idx < n; idx++) { \ + if (idx > 0) \ + av_bprint_chars(&pbuf, ' ', 1); \ + av_bprintf(&pbuf, f, __VA_ARGS__); \ + } \ + writer_print_string(w, k, pbuf.str, 0); \ +} while (0) + #define print_int(k, v) writer_print_integer(w, k, v) #define print_q(k, v, s) writer_print_rational(w, k, v, s) #define print_str(k, v) writer_print_string(w, k, v, 0) @@ -1836,7 +1856,7 @@ static void writer_register_all(void) static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id) { - AVDictionaryEntry *tag = NULL; + const AVDictionaryEntry *tag = NULL; int ret = 0; if (!tags) @@ -1852,6 +1872,153 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id return ret; } +static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi) +{ + if (!dovi) + return; + + { + const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + AVBPrint pbuf; + + av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED); + + // header + print_int("rpu_type", hdr->rpu_type); + print_int("rpu_format", hdr->rpu_format); + print_int("vdr_rpu_profile", hdr->vdr_rpu_profile); + print_int("vdr_rpu_level", hdr->vdr_rpu_level); + print_int("chroma_resampling_explicit_filter_flag", + hdr->chroma_resampling_explicit_filter_flag); + print_int("coef_data_type", hdr->coef_data_type); + print_int("coef_log2_denom", hdr->coef_log2_denom); + print_int("vdr_rpu_normalized_idc", hdr->vdr_rpu_normalized_idc); + print_int("bl_video_full_range_flag", hdr->bl_video_full_range_flag); + print_int("bl_bit_depth", hdr->bl_bit_depth); + print_int("el_bit_depth", hdr->el_bit_depth); + print_int("vdr_bit_depth", hdr->vdr_bit_depth); + print_int("spatial_resampling_filter_flag", + hdr->spatial_resampling_filter_flag); + print_int("el_spatial_resampling_filter_flag", + hdr->el_spatial_resampling_filter_flag); + print_int("disable_residual_flag", hdr->disable_residual_flag); + + // data mapping values + print_int("vdr_rpu_id", mapping->vdr_rpu_id); + print_int("mapping_color_space", mapping->mapping_color_space); + print_int("mapping_chroma_format_idc", + mapping->mapping_chroma_format_idc); + + print_int("nlq_method_idc", mapping->nlq_method_idc); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_NONE: + print_str("nlq_method_idc_name", "none"); + break; + case AV_DOVI_NLQ_LINEAR_DZ: + print_str("nlq_method_idc_name", "linear_dz"); + break; + default: + print_str("nlq_method_idc_name", "unknown"); + break; + } + + print_int("num_x_partitions", mapping->num_x_partitions); + print_int("num_y_partitions", mapping->num_y_partitions); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST); + + for (int c = 0; c < 3; c++) { + const AVDOVIReshapingCurve *curve = &mapping->curves[c]; + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT); + + print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, curve->pivots[idx]); + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST); + for (int i = 0; i < curve->num_pivots - 1; i++) { + + writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE); + print_int("mapping_idc", curve->mapping_idc[i]); + switch (curve->mapping_idc[i]) { + case AV_DOVI_MAPPING_POLYNOMIAL: + print_str("mapping_idc_name", "polynomial"); + print_int("poly_order", curve->poly_order[i]); + print_list_fmt("poly_coef", "%"PRIi64, + curve->poly_order[i] + 1, + curve->poly_coef[i][idx]); + break; + case AV_DOVI_MAPPING_MMR: + print_str("mapping_idc_name", "mmr"); + print_int("mmr_order", curve->mmr_order[i]); + print_int("mmr_constant", curve->mmr_constant[i]); + print_list_fmt("mmr_coef", "%"PRIi64, + curve->mmr_order[i] * 7, + curve->mmr_coef[i][0][idx]); + break; + default: + print_str("mapping_idc_name", "unknown"); + break; + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST + writer_print_section_footer(w); + + if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) { + const AVDOVINLQParams *nlq = &mapping->nlq[c]; + print_int("nlq_offset", nlq->nlq_offset); + print_int("vdr_in_max", nlq->vdr_in_max); + + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + print_int("linear_deadzone_slope", nlq->linear_deadzone_slope); + print_int("linear_deadzone_threshold", nlq->linear_deadzone_threshold); + break; + } + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT + writer_print_section_footer(w); + } + + // SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST + writer_print_section_footer(w); + + // color metadata + print_int("dm_metadata_id", color->dm_metadata_id); + print_int("scene_refresh_flag", color->scene_refresh_flag); + print_list_fmt("ycc_to_rgb_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_matrix), + color->ycc_to_rgb_matrix[idx].num, + color->ycc_to_rgb_matrix[idx].den); + print_list_fmt("ycc_to_rgb_offset", "%d/%d", + FF_ARRAY_ELEMS(color->ycc_to_rgb_offset), + color->ycc_to_rgb_offset[idx].num, + color->ycc_to_rgb_offset[idx].den); + print_list_fmt("rgb_to_lms_matrix", "%d/%d", + FF_ARRAY_ELEMS(color->rgb_to_lms_matrix), + color->rgb_to_lms_matrix[idx].num, + color->rgb_to_lms_matrix[idx].den); + print_int("signal_eotf", color->signal_eotf); + print_int("signal_eotf_param0", color->signal_eotf_param0); + print_int("signal_eotf_param1", color->signal_eotf_param1); + print_int("signal_eotf_param2", color->signal_eotf_param2); + print_int("signal_bit_depth", color->signal_bit_depth); + print_int("signal_color_space", color->signal_color_space); + print_int("signal_chroma_format", color->signal_chroma_format); + print_int("signal_full_range_flag", color->signal_full_range_flag); + print_int("source_min_pq", color->source_min_pq); + print_int("source_max_pq", color->source_max_pq); + print_int("source_diagonal", color->source_diagonal); + + av_bprint_finalize(&pbuf, NULL); + } +} + static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata) { if (!metadata) @@ -2364,10 +2531,12 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream, print_int("max_content", metadata->MaxCLL); print_int("max_average", metadata->MaxFALL); } else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) { - AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE); + const AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE); if (tag) print_str(tag->key, tag->value); print_int("size", sd->size); + } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) { + print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data); } writer_print_section_footer(w); } @@ -2769,6 +2938,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id par->extradata_size); if (par->extradata_size > 0) { + print_int("extradata_size", par->extradata_size); writer_print_data_hash(w, "extradata_hash", par->extradata, par->extradata_size); } @@ -2957,7 +3127,7 @@ static int open_input_file(InputFile *ifile, const char *filename, { int err, i; AVFormatContext *fmt_ctx = NULL; - AVDictionaryEntry *t = NULL; + const AVDictionaryEntry *t = NULL; int scan_all_pmts_set = 0; fmt_ctx = avformat_alloc_context(); diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 14fbd2ecbc..cfc70a3eaf 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -60,7 +60,7 @@ OBJS = ac3_parser.o \ # subsystems OBJS-$(CONFIG_AANDCTTABLES) += aandcttab.o OBJS-$(CONFIG_AC3DSP) += ac3dsp.o ac3.o ac3tab.o -OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio.o +OBJS-$(CONFIG_ADTS_HEADER) += adts_header.o mpeg4audio_sample_rates.o OBJS-$(CONFIG_AMF) += amfenc.o OBJS-$(CONFIG_AUDIO_FRAME_QUEUE) += audio_frame_queue.o OBJS-$(CONFIG_ATSC_A53) += atsc_a53.o @@ -77,6 +77,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_DOVI_RPU) += dovi_rpu.o OBJS-$(CONFIG_ERROR_RESILIENCE) += error_resilience.o OBJS-$(CONFIG_EXIF) += exif.o tiff_common.o OBJS-$(CONFIG_FAANDCT) += faandct.o @@ -117,20 +118,23 @@ OBJS-$(CONFIG_MDCT) += mdct_float.o mdct_fixed_32.o OBJS-$(CONFIG_ME_CMP) += me_cmp.o OBJS-$(CONFIG_MEDIACODEC) += mediacodecdec_common.o mediacodec_surface.o mediacodec_wrapper.o mediacodec_sw_buffer.o OBJS-$(CONFIG_MPEG_ER) += mpeg_er.o -OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o +OBJS-$(CONFIG_MPEGAUDIO) += mpegaudio.o mpegaudiodec_common.o \ + mpegaudiodata.o OBJS-$(CONFIG_MPEGAUDIODSP) += mpegaudiodsp.o \ mpegaudiodsp_data.o \ mpegaudiodsp_fixed.o \ mpegaudiodsp_float.o -OBJS-$(CONFIG_MPEGAUDIOHEADER) += mpegaudiodecheader.o mpegaudiodata.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 \ - mpegvideodata.o mpegpicture.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 OBJS-$(CONFIG_MSS34DSP) += mss34dsp.o -OBJS-$(CONFIG_NVENC) += nvenc.o OBJS-$(CONFIG_PIXBLOCKDSP) += pixblockdsp.o OBJS-$(CONFIG_QPELDSP) += qpeldsp.o OBJS-$(CONFIG_QSV) += qsv.o @@ -139,7 +143,6 @@ OBJS-$(CONFIG_QSVENC) += qsvenc.o OBJS-$(CONFIG_RANGECODER) += rangecoder.o OBJS-$(CONFIG_RDFT) += rdft.o OBJS-$(CONFIG_RV34DSP) += rv34dsp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o reverse.o OBJS-$(CONFIG_SINEWIN) += sinewin.o OBJS-$(CONFIG_SNAPPY) += snappy.o OBJS-$(CONFIG_STARTCODE) += startcode.o @@ -161,10 +164,10 @@ OBJS-$(CONFIG_ZERO12V_DECODER) += 012v.o OBJS-$(CONFIG_A64MULTI_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_A64MULTI5_ENCODER) += a64multienc.o elbg.o OBJS-$(CONFIG_AAC_DECODER) += aacdec.o aactab.o aacsbr.o aacps_common.o aacps_float.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp.o aacpsdsp_float.o cbrt_data.o OBJS-$(CONFIG_AAC_FIXED_DECODER) += aacdec_fixed.o aactab.o aacsbr_fixed.o aacps_common.o aacps_fixed.o \ - mpeg4audio.o kbdwin.o \ + kbdwin.o \ sbrdsp_fixed.o aacpsdsp_fixed.o cbrt_data_fixed.o OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacpsy.o aactab.o \ @@ -172,11 +175,14 @@ OBJS-$(CONFIG_AAC_ENCODER) += aacenc.o aaccoder.o aacenctab.o \ aacenc_tns.o \ aacenc_ltp.o \ aacenc_pred.o \ - psymodel.o mpeg4audio.o kbdwin.o + psymodel.o kbdwin.o \ + mpeg4audio_sample_rates.o OBJS-$(CONFIG_AAC_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_AASC_DECODER) += aasc.o msrledec.o -OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o -OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o kbdwin.o ac3tab.o +OBJS-$(CONFIG_AC3_DECODER) += ac3dec_float.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o +OBJS-$(CONFIG_AC3_FIXED_DECODER) += ac3dec_fixed.o ac3dec_data.o ac3.o \ + kbdwin.o ac3tab.o ac3_channel_layout_tab.o OBJS-$(CONFIG_AC3_ENCODER) += ac3enc_float.o ac3enc.o ac3tab.o \ ac3.o kbdwin.o OBJS-$(CONFIG_AC3_FIXED_ENCODER) += ac3enc_fixed.o ac3enc.o ac3tab.o ac3.o kbdwin.o @@ -188,7 +194,7 @@ OBJS-$(CONFIG_ALAC_DECODER) += alac.o alac_data.o alacdsp.o OBJS-$(CONFIG_ALAC_ENCODER) += alacenc.o alac_data.o OBJS-$(CONFIG_ALIAS_PIX_DECODER) += aliaspixdec.o OBJS-$(CONFIG_ALIAS_PIX_ENCODER) += aliaspixenc.o -OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o mpeg4audio.o +OBJS-$(CONFIG_ALS_DECODER) += alsdec.o bgmc.o mlz.o OBJS-$(CONFIG_AMRNB_DECODER) += amrnbdec.o celp_filters.o \ celp_math.o acelp_filters.o \ acelp_vectors.o \ @@ -243,7 +249,8 @@ OBJS-$(CONFIG_BINK_DECODER) += bink.o binkdsp.o OBJS-$(CONFIG_BINKAUDIO_DCT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINKAUDIO_RDFT_DECODER) += binkaudio.o OBJS-$(CONFIG_BINTEXT_DECODER) += bintext.o cga_data.o -OBJS-$(CONFIG_BITPACKED_DECODER) += bitpacked.o +OBJS-$(CONFIG_BITPACKED_DECODER) += bitpacked_dec.o +OBJS-$(CONFIG_BITPACKED_ENCODER) += bitpacked_enc.o OBJS-$(CONFIG_BMP_DECODER) += bmp.o msrledec.o OBJS-$(CONFIG_BMP_ENCODER) += bmpenc.o OBJS-$(CONFIG_BMV_AUDIO_DECODER) += bmvaudio.o @@ -273,7 +280,8 @@ OBJS-$(CONFIG_CSCD_DECODER) += cscd.o OBJS-$(CONFIG_CYUV_DECODER) += cyuv.o OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadata.o dcahuff.o \ dca_core.o dca_exss.o dca_xll.o dca_lbr.o \ - dcadsp.o dcadct.o synth_filter.o + dcadsp.o dcadct.o dca_sample_rate_tab.o \ + synth_filter.o OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dcadata.o dcahuff.o \ dcaadpcm.o OBJS-$(CONFIG_DDS_DECODER) += dds.o @@ -374,7 +382,7 @@ OBJS-$(CONFIG_H264_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_H264_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_H264_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_H264_MMAL_DECODER) += mmaldec.o -OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o +OBJS-$(CONFIG_H264_NVENC_ENCODER) += nvenc_h264.o nvenc.o OBJS-$(CONFIG_H264_OMX_ENCODER) += omx.o OBJS-$(CONFIG_H264_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_H264_QSV_ENCODER) += qsvenc_h264.o @@ -389,12 +397,13 @@ OBJS-$(CONFIG_HCA_DECODER) += hcadec.o OBJS-$(CONFIG_HCOM_DECODER) += hcom.o OBJS-$(CONFIG_HEVC_DECODER) += hevcdec.o hevc_mvs.o \ hevc_cabac.o hevc_refs.o hevcpred.o \ - hevcdsp.o hevc_filter.o hevc_data.o + hevcdsp.o hevc_filter.o hevc_data.o \ + h274.o OBJS-$(CONFIG_HEVC_AMF_ENCODER) += amfenc_hevc.o OBJS-$(CONFIG_HEVC_CUVID_DECODER) += cuviddec.o OBJS-$(CONFIG_HEVC_MEDIACODEC_DECODER) += mediacodecdec.o OBJS-$(CONFIG_HEVC_MF_ENCODER) += mfenc.o mf_utils.o -OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o +OBJS-$(CONFIG_HEVC_NVENC_ENCODER) += nvenc_hevc.o nvenc.o OBJS-$(CONFIG_HEVC_QSV_DECODER) += qsvdec.o OBJS-$(CONFIG_HEVC_QSV_ENCODER) += qsvenc_hevc.o hevc_ps_enc.o \ hevc_data.o @@ -402,6 +411,7 @@ OBJS-$(CONFIG_HEVC_RKMPP_DECODER) += rkmppdec.o OBJS-$(CONFIG_HEVC_VAAPI_ENCODER) += vaapi_encode_h265.o h265_profile_level.o OBJS-$(CONFIG_HEVC_V4L2M2M_DECODER) += v4l2_m2m_dec.o OBJS-$(CONFIG_HEVC_V4L2M2M_ENCODER) += v4l2_m2m_enc.o +OBJS-$(CONFIG_HEVC_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_HNM4_VIDEO_DECODER) += hnm4video.o OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ canopus.o @@ -467,17 +477,19 @@ OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP2_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP2_ENCODER) += mpegaudioenc_float.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FIXED_ENCODER) += mpegaudioenc_fixed.o mpegaudio.o \ - mpegaudiodata.o mpegaudiodsp_data.o + mpegaudiodata.o mpegaudiodsp_data.o \ + mpegaudiotabs.o OBJS-$(CONFIG_MP2FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3_MF_ENCODER) += mfenc.o mf_utils.o OBJS-$(CONFIG_MP3ADU_DECODER) += mpegaudiodec_fixed.o OBJS-$(CONFIG_MP3ADUFLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MP3FLOAT_DECODER) += mpegaudiodec_float.o -OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o mpeg4audio.o -OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o mpeg4audio.o +OBJS-$(CONFIG_MP3ON4_DECODER) += mpegaudiodec_fixed.o +OBJS-$(CONFIG_MP3ON4FLOAT_DECODER) += mpegaudiodec_float.o OBJS-$(CONFIG_MPC7_DECODER) += mpc7.o mpc.o OBJS-$(CONFIG_MPC8_DECODER) += mpc8.o mpc.o OBJS-$(CONFIG_MPEGVIDEO_DECODER) += mpeg12dec.o mpeg12.o mpeg12data.o @@ -563,6 +575,7 @@ OBJS-$(CONFIG_PRORES_DECODER) += proresdec2.o proresdsp.o proresdata.o OBJS-$(CONFIG_PRORES_ENCODER) += proresenc_anatoliy.o proresdata.o OBJS-$(CONFIG_PRORES_AW_ENCODER) += proresenc_anatoliy.o proresdata.o OBJS-$(CONFIG_PRORES_KS_ENCODER) += proresenc_kostya.o proresdata.o +OBJS-$(CONFIG_PRORES_VIDEOTOOLBOX_ENCODER) += videotoolboxenc.o OBJS-$(CONFIG_PROSUMER_DECODER) += prosumer.o OBJS-$(CONFIG_PSD_DECODER) += psd.o OBJS-$(CONFIG_PTX_DECODER) += ptx.o @@ -875,6 +888,7 @@ OBJS-$(CONFIG_ADPCM_G726LE_DECODER) += g726.o OBJS-$(CONFIG_ADPCM_G726LE_ENCODER) += g726.o OBJS-$(CONFIG_ADPCM_IMA_ACORN_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_AMV_DECODER) += adpcm.o adpcm_data.o +OBJS-$(CONFIG_ADPCM_IMA_AMV_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ALP_DECODER) += adpcm.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_ALP_ENCODER) += adpcmenc.o adpcm_data.o OBJS-$(CONFIG_ADPCM_IMA_APC_DECODER) += adpcm.o adpcm_data.o @@ -975,25 +989,30 @@ OBJS-$(CONFIG_VP9_DXVA2_HWACCEL) += dxva2_vp9.o OBJS-$(CONFIG_VP9_NVDEC_HWACCEL) += nvdec_vp9.o OBJS-$(CONFIG_VP9_VAAPI_HWACCEL) += vaapi_vp9.o OBJS-$(CONFIG_VP9_VDPAU_HWACCEL) += vdpau_vp9.o +OBJS-$(CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) += videotoolbox_vp9.o OBJS-$(CONFIG_VP8_QSV_HWACCEL) += qsvdec.o -# libavformat dependencies -OBJS-$(CONFIG_ISO_MEDIA) += mpeg4audio.o mpegaudiodata.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o reverse.o -OBJS-$(CONFIG_ADTS_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_DNXHD_DEMUXER) += dnxhddata.o +# General libavformat dependencies OBJS-$(CONFIG_FITS_DEMUXER) += fits.o -OBJS-$(CONFIG_LATM_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_AUDIO_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MATROSKA_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_MOV_DEMUXER) += ac3tab.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio.o -OBJS-$(CONFIG_MXF_MUXER) += dnxhddata.o -OBJS-$(CONFIG_NUT_MUXER) += mpegaudiodata.o -OBJS-$(CONFIG_RTP_MUXER) += mpeg4audio.o -OBJS-$(CONFIG_SPDIF_MUXER) += dca.o OBJS-$(CONFIG_TAK_DEMUXER) += tak.o -OBJS-$(CONFIG_WEBM_MUXER) += mpeg4audio.o + +# libavformat dependencies for static builds +STLIBOBJS-$(CONFIG_AVFORMAT) += to_upper4.o +STLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o +STLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o +STLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o +STLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o +STLIBOBJS-$(CONFIG_MXF_MUXER) += golomb.o +STLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o +STLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o +STLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +STLIBOBJS-$(CONFIG_RTP_MUXER) += golomb.o jpegtables.o \ + mpeg4audio_sample_rates.o +STLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o # libavfilter dependencies OBJS-$(CONFIG_ELBG_FILTER) += elbg.o @@ -1076,9 +1095,9 @@ OBJS-$(CONFIG_LIBZVBI_TELETEXT_DECODER) += libzvbi-teletextdec.o ass.o # parsers OBJS-$(CONFIG_AAC_LATM_PARSER) += latm_parser.o -OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o \ - mpeg4audio.o -OBJS-$(CONFIG_AC3_PARSER) += ac3tab.o aac_ac3_parser.o +OBJS-$(CONFIG_AAC_PARSER) += aac_parser.o aac_ac3_parser.o +OBJS-$(CONFIG_AC3_PARSER) += aac_ac3_parser.o ac3tab.o \ + ac3_channel_layout_tab.o OBJS-$(CONFIG_ADX_PARSER) += adx_parser.o adx.o OBJS-$(CONFIG_AMR_PARSER) += amr_parser.o OBJS-$(CONFIG_AV1_PARSER) += av1_parser.o @@ -1088,7 +1107,8 @@ OBJS-$(CONFIG_BMP_PARSER) += bmp_parser.o OBJS-$(CONFIG_CAVSVIDEO_PARSER) += cavs_parser.o OBJS-$(CONFIG_COOK_PARSER) += cook_parser.o OBJS-$(CONFIG_CRI_PARSER) += cri_parser.o -OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o +OBJS-$(CONFIG_DCA_PARSER) += dca_parser.o dca_exss.o dca.o \ + dca_sample_rate_tab.o OBJS-$(CONFIG_DIRAC_PARSER) += dirac_parser.o OBJS-$(CONFIG_DNXHD_PARSER) += dnxhd_parser.o dnxhddata.o OBJS-$(CONFIG_DOLBY_E_PARSER) += dolby_e_parser.o dolby_e_parse.o @@ -1135,7 +1155,7 @@ OBJS-$(CONFIG_XBM_PARSER) += xbm_parser.o OBJS-$(CONFIG_XMA_PARSER) += xma_parser.o # bitstream filters -OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o mpeg4audio.o +OBJS-$(CONFIG_AAC_ADTSTOASC_BSF) += aac_adtstoasc_bsf.o OBJS-$(CONFIG_AV1_METADATA_BSF) += av1_metadata_bsf.o OBJS-$(CONFIG_AV1_FRAME_MERGE_BSF) += av1_frame_merge_bsf.o OBJS-$(CONFIG_AV1_FRAME_SPLIT_BSF) += av1_frame_split_bsf.o @@ -1158,7 +1178,7 @@ OBJS-$(CONFIG_MJPEGA_DUMP_HEADER_BSF) += mjpega_dump_header_bsf.o OBJS-$(CONFIG_MPEG4_UNPACK_BFRAMES_BSF) += mpeg4_unpack_bframes_bsf.o OBJS-$(CONFIG_MOV2TEXTSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_MP3_HEADER_DECOMPRESS_BSF) += mp3_header_decompress_bsf.o \ - mpegaudiodata.o + mpegaudiotabs.o OBJS-$(CONFIG_MPEG2_METADATA_BSF) += mpeg2_metadata_bsf.o OBJS-$(CONFIG_NOISE_BSF) += noise_bsf.o OBJS-$(CONFIG_NULL_BSF) += null_bsf.o diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c index 11b0559e1c..7bbd4d5b2e 100644 --- a/libavcodec/aaccoder.c +++ b/libavcodec/aaccoder.c @@ -414,11 +414,10 @@ static void search_for_quantizers_fast(AVCodecContext *avctx, AACEncContext *s, start = 0; for (g = 0; g < sce->ics.num_swb; g++) { int nz = 0; - float uplim = 0.0f, energy = 0.0f; + float uplim = 0.0f; for (w2 = 0; w2 < sce->ics.group_len[w]; w2++) { FFPsyBand *band = &s->psy.ch[s->cur_channel].psy_bands[(w+w2)*16+g]; uplim += band->threshold; - energy += band->energy; if (band->energy <= band->threshold || band->threshold == 0.0f) { sce->zeroes[(w+w2)*16+g] = 1; continue; diff --git a/libavcodec/aacenc.c b/libavcodec/aacenc.c index e462566078..a1004c3e98 100644 --- a/libavcodec/aacenc.c +++ b/libavcodec/aacenc.c @@ -998,7 +998,7 @@ static av_cold int aac_encode_init(AVCodecContext *avctx) /* Samplerate */ for (i = 0; i < 16; i++) - if (avctx->sample_rate == avpriv_mpeg4audio_sample_rates[i]) + if (avctx->sample_rate == ff_mpeg4audio_sample_rates[i]) break; s->samplerate_index = i; ERROR_IF(s->samplerate_index == 16 || @@ -1143,7 +1143,7 @@ const AVCodec ff_aac_encoder = { .encode2 = aac_encode_frame, .close = aac_encode_end, .defaults = aac_encode_defaults, - .supported_samplerates = mpeg4audio_sample_rates, + .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, diff --git a/libavcodec/aacenctab.h b/libavcodec/aacenctab.h index f54dd16bed..33cb7ae95b 100644 --- a/libavcodec/aacenctab.h +++ b/libavcodec/aacenctab.h @@ -81,13 +81,6 @@ static const uint8_t aac_chan_maps[AAC_MAX_CHANNELS][AAC_MAX_CHANNELS] = { { 2, 0, 1, 6, 7, 4, 5, 3 }, }; -/* duplicated from avpriv_mpeg4audio_sample_rates to avoid shared build - * failures */ -static const int mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - /** bits needed to code codebook run value for long windows */ static const uint8_t run_value_bits_long[64] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, diff --git a/libavcodec/aarch64/fft_neon.S b/libavcodec/aarch64/fft_neon.S index 862039f97d..b4020fc8c7 100644 --- a/libavcodec/aarch64/fft_neon.S +++ b/libavcodec/aarch64/fft_neon.S @@ -36,6 +36,7 @@ function fft4_neon + AARCH64_VALID_JUMP_TARGET ld1 {v0.2s,v1.2s,v2.2s,v3.2s}, [x0] fadd v4.2s, v0.2s, v1.2s // r0+r1,i0+i1 @@ -58,6 +59,7 @@ function fft4_neon endfunc function fft8_neon + AARCH64_VALID_JUMP_TARGET mov x1, x0 ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0] @@ -108,6 +110,7 @@ function fft8_neon endfunc function fft16_neon + AARCH64_VALID_JUMP_TARGET mov x1, x0 ld1 {v0.2s, v1.2s, v2.2s, v3.2s}, [x0], #32 ld1 {v16.2s,v17.2s,v18.2s,v19.2s}, [x0], #32 @@ -337,6 +340,7 @@ endfunc .macro def_fft n, n2, n4 function fft\n\()_neon, align=6 + AARCH64_VALID_JUMP_TARGET sub sp, sp, #16 stp x28, x30, [sp] add x28, x0, #\n4*2*8 diff --git a/libavcodec/aarch64/h264idct_neon.S b/libavcodec/aarch64/h264idct_neon.S index 7de44205d3..7d2879b0ce 100644 --- a/libavcodec/aarch64/h264idct_neon.S +++ b/libavcodec/aarch64/h264idct_neon.S @@ -24,6 +24,7 @@ function ff_h264_idct_add_neon, export=1 .L_ff_h264_idct_add_neon: + AARCH64_VALID_CALL_TARGET ld1 {v0.4H, v1.4H, v2.4H, v3.4H}, [x1] sxtw x2, w2 movi v30.8H, #0 @@ -79,6 +80,7 @@ endfunc function ff_h264_idct_dc_add_neon, export=1 .L_ff_h264_idct_dc_add_neon: + AARCH64_VALID_CALL_TARGET sxtw x2, w2 mov w3, #0 ld1r {v2.8H}, [x1] @@ -266,6 +268,7 @@ endfunc function ff_h264_idct8_add_neon, export=1 .L_ff_h264_idct8_add_neon: + AARCH64_VALID_CALL_TARGET movi v19.8H, #0 sxtw x2, w2 ld1 {v24.8H, v25.8H}, [x1] @@ -330,6 +333,7 @@ endfunc function ff_h264_idct8_dc_add_neon, export=1 .L_ff_h264_idct8_dc_add_neon: + AARCH64_VALID_CALL_TARGET mov w3, #0 sxtw x2, w2 ld1r {v31.8H}, [x1] diff --git a/libavcodec/aarch64/hevcdsp_init_aarch64.c b/libavcodec/aarch64/hevcdsp_init_aarch64.c index c785e46f79..1e40be740c 100644 --- a/libavcodec/aarch64/hevcdsp_init_aarch64.c +++ b/libavcodec/aarch64/hevcdsp_init_aarch64.c @@ -75,7 +75,11 @@ 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; - c->sao_band_filter[0] = ff_hevc_sao_band_filter_8x8_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; } 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 f9fed8345b..d523bf584d 100644 --- a/libavcodec/aarch64/hevcdsp_sao_neon.S +++ b/libavcodec/aarch64/hevcdsp_sao_neon.S @@ -30,24 +30,21 @@ // 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 + ld1 {v16.16b-v19.16b}, [sp], #64 + 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 +52,21 @@ 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 - subs w8, w8, #8 + ld1 {v2.8b}, [x1] // dst[x] = av_clip_pixel(src[x] + offset_table[src[x] >> shift]); + 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] // store + subs w8, w8, #8 // 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 diff --git a/libavcodec/aarch64/simple_idct_neon.S b/libavcodec/aarch64/simple_idct_neon.S index 5e4d021a97..210182ff21 100644 --- a/libavcodec/aarch64/simple_idct_neon.S +++ b/libavcodec/aarch64/simple_idct_neon.S @@ -58,7 +58,7 @@ endconst .endm .macro idct_end - br x10 + ret x10 .endm .macro smull1 a, b, c diff --git a/libavcodec/aarch64/vp9itxfm_16bpp_neon.S b/libavcodec/aarch64/vp9itxfm_16bpp_neon.S index 68296d9c40..c5f43d36a3 100644 --- a/libavcodec/aarch64/vp9itxfm_16bpp_neon.S +++ b/libavcodec/aarch64/vp9itxfm_16bpp_neon.S @@ -1040,7 +1040,7 @@ function \txfm\()16_1d_4x16_pass1_neon .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the last input column (x1 == 12), // which would be stored as the last row in the temp buffer, @@ -1068,7 +1068,7 @@ function \txfm\()16_1d_4x16_pass1_neon mov v29.16b, v17.16b mov v30.16b, v18.16b mov v31.16b, v19.16b - br x14 + ret x14 endfunc // Read a vertical 4x16 slice out of a 16x16 matrix, do a transform on it, @@ -1098,7 +1098,7 @@ function \txfm\()16_1d_4x16_pass2_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc .endm @@ -1208,7 +1208,7 @@ function vp9_\txfm1\()_\txfm2\()_16x16_add_16_neon ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x15 + ret x15 endfunc function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_10_neon, export=1 @@ -1264,7 +1264,7 @@ function idct16_1d_4x16_pass1_quarter_neon st1 {v23.4s}, [x0], #16 st1 {v27.4s}, [x0], #16 st1 {v31.4s}, [x0], #16 - br x14 + ret x14 endfunc function idct16_1d_4x16_pass2_quarter_neon @@ -1286,7 +1286,7 @@ function idct16_1d_4x16_pass2_quarter_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc function idct16_1d_4x16_pass1_half_neon @@ -1313,7 +1313,7 @@ function idct16_1d_4x16_pass1_half_neon .irp i, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the second input column (r1 == 4), // which would be stored as the second row in the temp buffer, @@ -1341,7 +1341,7 @@ function idct16_1d_4x16_pass1_half_neon mov v21.16b, v17.16b mov v22.16b, v18.16b mov v23.16b, v19.16b - br x14 + ret x14 endfunc function idct16_1d_4x16_pass2_half_neon @@ -1364,7 +1364,7 @@ function idct16_1d_4x16_pass2_half_neon load_add_store v16.4s, v17.4s, v18.4s, v19.4s, v20.4s, v21.4s, v22.4s, v23.4s load_add_store v24.4s, v25.4s, v26.4s, v27.4s, v28.4s, v29.4s, v30.4s, v31.4s - br x14 + ret x14 endfunc .macro idct16_partial size @@ -1390,7 +1390,7 @@ function idct16x16_\size\()_add_16_neon add sp, sp, #1024 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc .endm @@ -1729,7 +1729,7 @@ function idct32_1d_4x32_pass1\suffix\()_neon store_rev v29.4s, v25.4s, v21.4s, v17.4s, v29.16b, v25.16b store_rev v28.4s, v24.4s, v20.4s, v16.4s, v28.16b, v24.16b .purgem store_rev - br x14 + ret x14 endfunc // This is mostly the same as 4x32_pass1, but without the transpose, @@ -1849,7 +1849,7 @@ function idct32_1d_4x32_pass2\suffix\()_neon load_acc_store v24.4s, v25.4s, v26.4s, v27.4s, 1 load_acc_store v28.4s, v29.4s, v30.4s, v31.4s, 1 .purgem load_acc_store - br x14 + ret x14 endfunc .endm @@ -1943,7 +1943,7 @@ function vp9_idct_idct_32x32_add_16_neon ldp d10, d11, [sp], 0x10 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc function ff_vp9_idct_idct_32x32_add_10_neon, export=1 @@ -2009,7 +2009,7 @@ function idct32x32_\size\()_add_16_neon ldp d10, d11, [sp], 0x10 ldp d8, d9, [sp], 0x10 - br x15 + ret x15 endfunc .endm diff --git a/libavcodec/aarch64/vp9itxfm_neon.S b/libavcodec/aarch64/vp9itxfm_neon.S index 99413b0f70..03272eae82 100644 --- a/libavcodec/aarch64/vp9itxfm_neon.S +++ b/libavcodec/aarch64/vp9itxfm_neon.S @@ -787,7 +787,7 @@ function \txfm\()16_1d_8x16_pass1_neon .irp i, 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 22, 30, 23, 31 store \i, x0, #16 .endr - br x14 + ret x14 1: // Special case: For the last input column (x1 == 8), // which would be stored as the last row in the temp buffer, @@ -806,7 +806,7 @@ function \txfm\()16_1d_8x16_pass1_neon mov v29.16b, v21.16b mov v30.16b, v22.16b mov v31.16b, v23.16b - br x14 + ret x14 endfunc // Read a vertical 8x16 slice out of a 16x16 matrix, do a transform on it, @@ -834,7 +834,7 @@ function \txfm\()16_1d_8x16_pass2_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc .endm @@ -925,7 +925,7 @@ function ff_vp9_\txfm1\()_\txfm2\()_16x16_add_neon, export=1 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x15 + ret x15 endfunc .endm @@ -960,7 +960,7 @@ function idct16_1d_8x16_pass1_quarter_neon .irp i, 24, 25, 26, 27 store \i, x0, x9 .endr - br x14 + ret x14 endfunc function idct16_1d_8x16_pass2_quarter_neon @@ -978,7 +978,7 @@ function idct16_1d_8x16_pass2_quarter_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc function idct16_1d_8x16_pass1_half_neon @@ -1003,7 +1003,7 @@ function idct16_1d_8x16_pass1_half_neon .irp i, 24, 25, 26, 27, 28, 29, 30, 31 store \i, x0, x9 .endr - br x14 + ret x14 endfunc function idct16_1d_8x16_pass2_half_neon @@ -1021,7 +1021,7 @@ function idct16_1d_8x16_pass2_half_neon load_add_store v16.8h, v17.8h, v18.8h, v19.8h, v20.8h, v21.8h, v22.8h, v23.8h, v16.8b, v17.8b load_add_store v24.8h, v25.8h, v26.8h, v27.8h, v28.8h, v29.8h, v30.8h, v31.8h, v16.8b, v17.8b - br x14 + ret x14 endfunc .macro idct16_partial size @@ -1038,7 +1038,7 @@ function idct16x16_\size\()_add_neon .endr add sp, sp, #512 - br x15 + ret x15 endfunc .endm @@ -1349,7 +1349,7 @@ function idct32_1d_8x32_pass1\suffix\()_neon store_rev v25.8h, v17.8h store_rev v24.8h, v16.8h .purgem store_rev - br x14 + ret x14 endfunc // This is mostly the same as 8x32_pass1, but without the transpose, @@ -1466,7 +1466,7 @@ function idct32_1d_8x32_pass2\suffix\()_neon load_acc_store v24.8h, v25.8h, v26.8h, v27.8h, 1 load_acc_store v28.8h, v29.8h, v30.8h, v31.8h, 1 .purgem load_acc_store - br x14 + ret x14 endfunc .endm @@ -1547,7 +1547,7 @@ function ff_vp9_idct_idct_32x32_add_neon, export=1 ldp d8, d9, [sp], 0x10 ldp d10, d11, [sp], 0x10 - br x15 + ret x15 endfunc .macro idct32_partial size @@ -1572,7 +1572,7 @@ function idct32x32_\size\()_add_neon ldp d8, d9, [sp], 0x10 ldp d10, d11, [sp], 0x10 - br x15 + ret x15 endfunc .endm diff --git a/libavcodec/aarch64/vp9lpf_16bpp_neon.S b/libavcodec/aarch64/vp9lpf_16bpp_neon.S index 9869614a29..a092617b92 100644 --- a/libavcodec/aarch64/vp9lpf_16bpp_neon.S +++ b/libavcodec/aarch64/vp9lpf_16bpp_neon.S @@ -57,7 +57,7 @@ mov x12, v4.d[1] adds x11, x11, x12 b.ne 1f - br x10 + ret x10 1: .if \wd >= 8 @@ -193,7 +193,7 @@ b.eq 6f .else b.ne 1f - br x13 + ret x13 1: .endif @@ -252,7 +252,7 @@ b.ne 1f // If no pixels needed flat8in nor flat8out, jump to a // writeout of the inner 4 pixels - br x14 + ret x14 1: mov x11, v7.d[0] @@ -260,7 +260,7 @@ adds x11, x11, x12 b.ne 1f // If no pixels need flat8out, jump to a writeout of the inner 6 pixels - br x15 + ret x15 1: // flat8out @@ -434,7 +434,7 @@ function ff_\func\()_\bpp\()_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x16 + ret x16 .else b \func\()_16_neon .endif @@ -474,7 +474,7 @@ function ff_\func\()_\suffix\()_\bpp\()_neon, export=1 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 .endif - br x16 + ret x16 endfunc .endm @@ -508,7 +508,7 @@ function ff_vp9_loop_filter_\dir\()_\wd1\()\wd2\()_16_\bpp\()_neon, export=1 lsl w3, w14, #\bpp - 8 lsl w4, w15, #\bpp - 8 bl vp9_loop_filter_\dir\()_\wd2\()_8_16_neon - br x16 + ret x16 endfunc .endm @@ -541,7 +541,7 @@ function vp9_loop_filter_v_4_8_16_neon st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_4_8 @@ -589,7 +589,7 @@ function vp9_loop_filter_h_4_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_4_8 @@ -620,7 +620,7 @@ function vp9_loop_filter_v_8_8_16_neon sub x0, x0, x1, lsl #1 sub x0, x0, x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.8h}, [x9], x1 @@ -628,7 +628,7 @@ function vp9_loop_filter_v_8_8_16_neon st1 {v23.8h}, [x9], x1 st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_8_8 @@ -671,7 +671,7 @@ function vp9_loop_filter_h_8_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, #8 - br x10 + ret x10 6: // If we didn't need to do the flat8in part, we use the same writeback // as in loop_filter_h_4_8. @@ -688,7 +688,7 @@ function vp9_loop_filter_h_8_8_16_neon st1 {v25.d}[1], [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_8_8 @@ -743,7 +743,7 @@ function vp9_loop_filter_v_16_8_16_neon sub x0, x0, x1, lsl #3 add x0, x0, x1 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 // If we didn't do the flat8out part, the output is left in the @@ -756,7 +756,7 @@ function vp9_loop_filter_v_16_8_16_neon st1 {v26.8h}, [x0], x1 sub x0, x0, x1, lsl #1 sub x0, x0, x1 - br x10 + ret x10 7: sub x9, x0, x1, lsl #1 st1 {v22.8h}, [x9], x1 @@ -764,7 +764,7 @@ function vp9_loop_filter_v_16_8_16_neon st1 {v23.8h}, [x9], x1 st1 {v25.8h}, [x0], x1 sub x0, x0, x1, lsl #1 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_v_16_8, push=1 @@ -821,7 +821,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v31.8h}, [x0], x1 sub x0, x0, x1, lsl #3 - br x10 + ret x10 8: // The same writeback as in loop_filter_h_8_8 sub x9, x0, #8 @@ -838,7 +838,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v27.8h}, [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #8 - br x10 + ret x10 7: // The same writeback as in loop_filter_h_4_8 sub x9, x0, #4 @@ -854,7 +854,7 @@ function vp9_loop_filter_h_16_8_16_neon st1 {v25.d}[1], [x0], x1 sub x0, x0, x1, lsl #3 add x0, x0, #4 - br x10 + ret x10 endfunc bpp_frontends vp9_loop_filter_h_16_8, push=1 diff --git a/libavcodec/aarch64/vp9lpf_neon.S b/libavcodec/aarch64/vp9lpf_neon.S index 0878763020..694ff8956f 100644 --- a/libavcodec/aarch64/vp9lpf_neon.S +++ b/libavcodec/aarch64/vp9lpf_neon.S @@ -399,7 +399,7 @@ .endif // If no pixels needed flat8in nor flat8out, jump to a // writeout of the inner 4 pixels - br x14 + ret x14 1: mov x5, v7.d[0] @@ -411,7 +411,7 @@ cbnz x5, 1f .endif // If no pixels need flat8out, jump to a writeout of the inner 6 pixels - br x15 + ret x15 1: // flat8out @@ -532,32 +532,32 @@ function vp9_loop_filter_4 loop_filter 4, .8b, 0, v16, v17, v18, v19, v28, v29, v30, v31 ret 9: - br x10 + ret x10 endfunc function vp9_loop_filter_4_16b_mix_44 loop_filter 4, .16b, 44, v16, v17, v18, v19, v28, v29, v30, v31 ret 9: - br x10 + ret x10 endfunc function vp9_loop_filter_8 loop_filter 8, .8b, 0, v16, v17, v18, v19, v28, v29, v30, v31 ret 6: - br x13 + ret x13 9: - br x10 + ret x10 endfunc function vp9_loop_filter_8_16b_mix loop_filter 8, .16b, 88, v16, v17, v18, v19, v28, v29, v30, v31 ret 6: - br x13 + ret x13 9: - br x10 + ret x10 endfunc function vp9_loop_filter_16 @@ -568,7 +568,7 @@ function vp9_loop_filter_16 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 endfunc function vp9_loop_filter_16_16b @@ -579,7 +579,7 @@ function vp9_loop_filter_16_16b ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 endfunc .macro loop_filter_4 @@ -648,7 +648,7 @@ function ff_vp9_loop_filter_v_4_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v25.8b}, [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_v_44_16_neon, export=1 @@ -672,7 +672,7 @@ function ff_vp9_loop_filter_v_44_16_neon, export=1 st1 {v23.16b}, [x9], x1 st1 {v25.16b}, [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_h_4_8_neon, export=1 @@ -714,7 +714,7 @@ function ff_vp9_loop_filter_h_4_8_neon, export=1 st1 {v25.s}[0], [x9], x1 st1 {v25.s}[1], [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_h_44_16_neon, export=1 @@ -766,7 +766,7 @@ function ff_vp9_loop_filter_h_44_16_neon, export=1 st1 {v25.s}[1], [x9], x1 st1 {v25.s}[3], [x0], x1 - br x10 + ret x10 endfunc function ff_vp9_loop_filter_v_8_8_neon, export=1 @@ -793,14 +793,14 @@ function ff_vp9_loop_filter_v_8_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v26.8b}, [x0], x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.8b}, [x9], x1 st1 {v24.8b}, [x0], x1 st1 {v23.8b}, [x9], x1 st1 {v25.8b}, [x0], x1 - br x10 + ret x10 endfunc .macro mix_v_16 mix @@ -828,14 +828,14 @@ function ff_vp9_loop_filter_v_\mix\()_16_neon, export=1 st1 {v23.16b}, [x9], x1 st1 {v26.16b}, [x0], x1 - br x10 + ret x10 6: sub x9, x0, x1, lsl #1 st1 {v22.16b}, [x9], x1 st1 {v24.16b}, [x0], x1 st1 {v23.16b}, [x9], x1 st1 {v25.16b}, [x0], x1 - br x10 + ret x10 endfunc .endm @@ -876,7 +876,7 @@ function ff_vp9_loop_filter_h_8_8_neon, export=1 st1 {v23.8b}, [x9], x1 st1 {v27.8b}, [x0], x1 - br x10 + ret x10 6: // If we didn't need to do the flat8in part, we use the same writeback // as in loop_filter_h_4_8. @@ -891,7 +891,7 @@ function ff_vp9_loop_filter_h_8_8_neon, export=1 st1 {v24.s}[1], [x0], x1 st1 {v25.s}[0], [x9], x1 st1 {v25.s}[1], [x0], x1 - br x10 + ret x10 endfunc .macro mix_h_16 mix @@ -942,7 +942,7 @@ function ff_vp9_loop_filter_h_\mix\()_16_neon, export=1 st1 {v27.8b}, [x9], x1 st1 {v27.d}[1], [x0], x1 - br x10 + ret x10 6: add x9, x9, #2 add x0, x0, #2 @@ -963,7 +963,7 @@ function ff_vp9_loop_filter_h_\mix\()_16_neon, export=1 st1 {v24.s}[3], [x0], x1 st1 {v25.s}[1], [x9], x1 st1 {v25.s}[3], [x0], x1 - br x10 + ret x10 endfunc .endm @@ -1022,7 +1022,7 @@ function ff_vp9_loop_filter_v_16_8_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 // If we didn't do the flat8out part, the output is left in the @@ -1091,7 +1091,7 @@ function ff_vp9_loop_filter_v_16_16_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: add x9, x9, x1, lsl #2 st1 {v21.16b}, [x9], x1 @@ -1168,7 +1168,7 @@ function ff_vp9_loop_filter_h_16_8_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: // The same writeback as in loop_filter_h_8_8 sub x9, x0, #4 @@ -1287,7 +1287,7 @@ function ff_vp9_loop_filter_h_16_16_neon, export=1 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 - br x10 + ret x10 8: sub x9, x0, #4 add x0, x9, x1, lsl #3 diff --git a/libavcodec/ac3_channel_layout_tab.c b/libavcodec/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..4fed46b6e7 --- /dev/null +++ b/libavcodec/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ac3_channel_layout_tab.h" diff --git a/libavfilter/glslang.h b/libavcodec/ac3_channel_layout_tab.h similarity index 57% rename from libavfilter/glslang.h rename to libavcodec/ac3_channel_layout_tab.h index d33808b945..46fa9ecdfe 100644 --- a/libavfilter/glslang.h +++ b/libavcodec/ac3_channel_layout_tab.h @@ -1,4 +1,7 @@ /* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -16,37 +19,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef AVFILTER_GLSLANG_H -#define AVFILTER_GLSLANG_H +#ifndef AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H +#define AVCODEC_AC3_CHANNEL_LAYOUT_TAB_H -#include +#include +#include "libavutil/channel_layout.h" -#ifdef __cplusplus -extern "C" { -#endif - -int glslang_init(void); -void glslang_uninit(void); - -typedef struct GLSlangResult { - int rval; - char *error_msg; - - void *data; /* Shader data or NULL */ - size_t size; -} GLSlangResult; - -enum GLSlangStage { - GLSLANG_VERTEX, - GLSLANG_FRAGMENT, - GLSLANG_COMPUTE, +/** + * Map audio coding mode (acmod) to channel layout mask. + */ +const uint16_t ff_ac3_channel_layout_tab[8] = { + AV_CH_LAYOUT_STEREO, + 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 }; - -/* Compile GLSL into a SPIRV stream, if possible */ -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage); - -#ifdef __cplusplus -} #endif - -#endif /* AVFILTER_GLSLANG_H */ diff --git a/libavcodec/ac3_parser.c b/libavcodec/ac3_parser.c index 9ed6ede5c3..f3c7d27d59 100644 --- a/libavcodec/ac3_parser.c +++ b/libavcodec/ac3_parser.c @@ -141,7 +141,7 @@ int ff_ac3_parse_header(GetBitContext *gbc, AC3HeaderInfo *hdr) (hdr->num_blocks * 256); hdr->channels = ff_ac3_channels_tab[hdr->channel_mode] + hdr->lfe_on; } - hdr->channel_layout = avpriv_ac3_channel_layout_tab[hdr->channel_mode]; + hdr->channel_layout = ff_ac3_channel_layout_tab[hdr->channel_mode]; if (hdr->lfe_on) hdr->channel_layout |= AV_CH_LOW_FREQUENCY; diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index c7deb56e1c..ae00373dcb 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1616,7 +1616,7 @@ dependent_frame: return AVERROR_INVALIDDATA; } avctx->channels = s->out_channels; - avctx->channel_layout = avpriv_ac3_channel_layout_tab[s->output_mode & ~AC3_OUTPUT_LFEON]; + avctx->channel_layout = 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; @@ -1700,7 +1700,7 @@ skip: extended_channel_map[ch] = ch; if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { - uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; + uint64_t ich_layout = ff_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on; uint64_t channel_layout; int extend = 0; diff --git a/libavcodec/ac3enc.h b/libavcodec/ac3enc.h index ec9ead8a4e..39a41fe0b0 100644 --- a/libavcodec/ac3enc.h +++ b/libavcodec/ac3enc.h @@ -35,6 +35,7 @@ #include "ac3dsp.h" #include "avcodec.h" #include "fft.h" +#include "internal.h" #include "mathops.h" #include "me_cmp.h" #include "put_bits.h" diff --git a/libavcodec/ac3tab.c b/libavcodec/ac3tab.c index 5c5ea7e27e..766e293a1d 100644 --- a/libavcodec/ac3tab.c +++ b/libavcodec/ac3tab.c @@ -82,20 +82,6 @@ const uint8_t ff_ac3_channels_tab[8] = { 2, 1, 2, 3, 3, 4, 4, 5 }; -/** - * Map audio coding mode (acmod) to channel layout mask. - */ -const uint16_t avpriv_ac3_channel_layout_tab[8] = { - AV_CH_LAYOUT_STEREO, - 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 -}; - /** * Table to remap channels from AC-3 order to SMPTE order. * [channel_mode][lfe][ch] diff --git a/libavcodec/ac3tab.h b/libavcodec/ac3tab.h index ea8e3340c7..bc470204fe 100644 --- a/libavcodec/ac3tab.h +++ b/libavcodec/ac3tab.h @@ -24,13 +24,11 @@ #include -#include "libavutil/internal.h" #include "ac3.h" -#include "internal.h" extern const uint16_t ff_ac3_frame_size_tab[38][3]; extern const uint8_t ff_ac3_channels_tab[8]; -extern av_export_avcodec const uint16_t avpriv_ac3_channel_layout_tab[8]; +extern const uint16_t ff_ac3_channel_layout_tab[8]; extern const uint8_t ff_ac3_dec_channel_map[8][2][6]; extern const int ff_ac3_sample_rate_tab[]; extern const uint16_t ff_ac3_bitrate_tab[19]; diff --git a/libavcodec/adts_header.c b/libavcodec/adts_header.c index e4454529c4..ff4efafbf7 100644 --- a/libavcodec/adts_header.c +++ b/libavcodec/adts_header.c @@ -40,7 +40,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) crc_abs = get_bits1(gbc); /* protection_absent */ aot = get_bits(gbc, 2); /* profile_objecttype */ sr = get_bits(gbc, 4); /* sample_frequency_index */ - if (!avpriv_mpeg4audio_sample_rates[sr]) + if (!ff_mpeg4audio_sample_rates[sr]) return AAC_AC3_PARSE_ERROR_SAMPLE_RATE; skip_bits1(gbc); /* private_bit */ ch = get_bits(gbc, 3); /* channel_configuration */ @@ -63,7 +63,7 @@ int ff_adts_header_parse(GetBitContext *gbc, AACADTSHeaderInfo *hdr) hdr->crc_absent = crc_abs; hdr->num_aac_frames = rdb + 1; hdr->sampling_index = sr; - hdr->sample_rate = avpriv_mpeg4audio_sample_rates[sr]; + hdr->sample_rate = ff_mpeg4audio_sample_rates[sr]; hdr->samples = (rdb + 1) * 1024; hdr->bit_rate = size * 8 * hdr->sample_rate / hdr->samples; hdr->frame_length = size; diff --git a/libavcodec/alacdsp.c b/libavcodec/alacdsp.c index 9996eb4319..8718d1b6b1 100644 --- a/libavcodec/alacdsp.c +++ b/libavcodec/alacdsp.c @@ -34,7 +34,7 @@ static void decorrelate_stereo(int32_t *buffer[2], int nb_samples, a = buffer[0][i]; b = buffer[1][i]; - a -= (b * decorr_left_weight) >> decorr_shift; + a -= (int)(b * (unsigned)decorr_left_weight) >> decorr_shift; b += a; buffer[0][i] = b; diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 9ede09be17..d1e10197de 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -65,6 +65,7 @@ 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; @@ -836,6 +837,7 @@ 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; diff --git a/libavcodec/apedec.c b/libavcodec/apedec.c index 9c723f2997..607304fe36 100644 --- a/libavcodec/apedec.c +++ b/libavcodec/apedec.c @@ -102,7 +102,7 @@ typedef struct APEFilter { int16_t *historybuffer; ///< filter memory int16_t *delay; ///< filtered values - int avg; + uint32_t avg; } APEFilter; typedef struct APERice { @@ -1088,13 +1088,13 @@ static av_always_inline int predictor_update_3930(APEPredictor *p, const int delayA) { int32_t predictionA, sign; - int32_t d0, d1, d2, d3; + uint32_t d0, d1, d2, d3; p->buf[delayA] = p->lastA[filter]; d0 = p->buf[delayA ]; - d1 = p->buf[delayA ] - p->buf[delayA - 1]; - d2 = p->buf[delayA - 1] - p->buf[delayA - 2]; - d3 = p->buf[delayA - 2] - p->buf[delayA - 3]; + d1 = p->buf[delayA ] - (unsigned)p->buf[delayA - 1]; + d2 = p->buf[delayA - 1] - (unsigned)p->buf[delayA - 2]; + d3 = p->buf[delayA - 2] - (unsigned)p->buf[delayA - 3]; predictionA = d0 * p->coeffsA[filter][0] + d1 * p->coeffsA[filter][1] + @@ -1105,10 +1105,10 @@ static av_always_inline int predictor_update_3930(APEPredictor *p, p->filterA[filter] = p->lastA[filter] + ((int)(p->filterA[filter] * 31U) >> 5); sign = APESIGN(decoded); - p->coeffsA[filter][0] += ((d0 < 0) * 2 - 1) * sign; - p->coeffsA[filter][1] += ((d1 < 0) * 2 - 1) * sign; - p->coeffsA[filter][2] += ((d2 < 0) * 2 - 1) * sign; - p->coeffsA[filter][3] += ((d3 < 0) * 2 - 1) * sign; + p->coeffsA[filter][0] += (((int32_t)d0 < 0) * 2 - 1) * sign; + p->coeffsA[filter][1] += (((int32_t)d1 < 0) * 2 - 1) * sign; + p->coeffsA[filter][2] += (((int32_t)d2 < 0) * 2 - 1) * sign; + p->coeffsA[filter][3] += (((int32_t)d3 < 0) * 2 - 1) * sign; return p->filterA[filter]; } @@ -1587,7 +1587,7 @@ static int ape_decode_frame(AVCodecContext *avctx, void *data, for (ch = 0; ch < s->channels; ch++) { sample8 = (uint8_t *)frame->data[ch]; for (i = 0; i < blockstodecode; i++) - *sample8++ = (s->decoded[ch][i] + 0x80) & 0xff; + *sample8++ = (s->decoded[ch][i] + 0x80U) & 0xff; } break; case 16: diff --git a/libavcodec/arm/hevcdsp_init_neon.c b/libavcodec/arm/hevcdsp_init_neon.c index 201a088dac..112edb5edd 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 f71bec05ed..caa6efa766 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/ass.c b/libavcodec/ass.c index 907e2d7b88..725e4d42ba 100644 --- a/libavcodec/ass.c +++ b/libavcodec/ass.c @@ -118,22 +118,22 @@ int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, int readorder, int layer, const char *style, const char *speaker) { + AVSubtitleRect **rects, *rect; char *ass_str; - AVSubtitleRect **rects; rects = av_realloc_array(sub->rects, sub->num_rects+1, sizeof(*sub->rects)); if (!rects) return AVERROR(ENOMEM); sub->rects = rects; - rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); - if (!rects[sub->num_rects]) + rect = av_mallocz(sizeof(*rect)); + if (!rect) return AVERROR(ENOMEM); - rects[sub->num_rects]->type = SUBTITLE_ASS; + rects[sub->num_rects++] = rect; + rect->type = SUBTITLE_ASS; ass_str = ff_ass_get_dialog(readorder, layer, style, speaker, dialog); if (!ass_str) return AVERROR(ENOMEM); - rects[sub->num_rects]->ass = ass_str; - sub->num_rects++; + rect->ass = ass_str; return 0; } diff --git a/libavcodec/atsc_a53.c b/libavcodec/atsc_a53.c index 2d89ef50b9..29ec71bc5f 100644 --- a/libavcodec/atsc_a53.c +++ b/libavcodec/atsc_a53.c @@ -73,7 +73,7 @@ int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size) int ret, cc_count; if (size < 3) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; ret = init_get_bits8(&gb, data, size); if (ret < 0) @@ -95,12 +95,12 @@ int ff_parse_a53_cc(AVBufferRef **pbuf, const uint8_t *data, int size) /* 3 bytes per CC plus one byte marker_bits at the end */ if (cc_count * 3 >= (get_bits_left(&gb) >> 3)) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; new_size = (old_size + cc_count * 3); if (new_size > INT_MAX) - return AVERROR(EINVAL); + return AVERROR_INVALIDDATA; /* Allow merging of the cc data from two fields. */ ret = av_buffer_realloc(pbuf, new_size); diff --git a/libavcodec/av1_metadata_bsf.c b/libavcodec/av1_metadata_bsf.c index 1fb85d88b7..c52673bf6a 100644 --- a/libavcodec/av1_metadata_bsf.c +++ b/libavcodec/av1_metadata_bsf.c @@ -194,7 +194,7 @@ static const AVOption av1_metadata_options[] = { { "colocated", "Top-left chroma sample position", 0, AV_OPT_TYPE_CONST, { .i64 = AV1_CSP_COLOCATED }, .flags = FLAGS, .unit = "csp" }, - { "tick_rate", "Set display tick rate (num_units_in_display_tick / time_scale)", + { "tick_rate", "Set display tick rate (time_scale / num_units_in_display_tick)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "num_ticks_per_picture", "Set display ticks per picture for CFR streams", diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index db110c50c7..62d459cded 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -585,16 +585,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->tf.f->buf[0]) + return 0; + + ret = ff_thread_ref_frame(&dst->tf, &src->tf); + 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) @@ -800,12 +803,6 @@ 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) goto fail; @@ -945,8 +942,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 +958,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 +987,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); @@ -1077,8 +1086,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 +1101,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.tf.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 +1121,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.tf.f->buf[0]) { ret = avctx->hwaccel->start_frame(avctx, unit->data, unit->data_size); if (ret < 0) { @@ -1138,7 +1148,7 @@ static int av1_decode_frame(AVCodecContext *avctx, void *frame, if (ret < 0) goto end; - if (avctx->hwaccel) { + if (avctx->hwaccel && s->cur_frame.tf.f->buf[0]) { ret = avctx->hwaccel->decode_slice(avctx, raw_tile_group->tile_data.data, raw_tile_group->tile_data.data_size); @@ -1161,7 +1171,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.tf.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 +1185,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.tf.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"); @@ -1240,6 +1250,7 @@ const AVCodec ff_av1_decoder = { .flush = av1_decode_flush, .profiles = NULL_IF_CONFIG_SMALL(ff_av1_profiles), .priv_class = &av1_class, + .bsfs = "av1_frame_split", .hw_configs = (const AVCodecHWConfigInternal *const []) { #if CONFIG_AV1_DXVA2_HWACCEL HWACCEL_DXVA2(av1), diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c index ff3d73e237..c00a9b2af8 100644 --- a/libavcodec/avcodec.c +++ b/libavcodec/avcodec.c @@ -181,11 +181,11 @@ 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->ds.in_pkt = av_packet_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->ds.in_pkt || + !avci->es.in_frame || !avci->in_pkt || !avci->last_pkt_props || !avci->pkt_props) { ret = AVERROR(ENOMEM); goto free_and_end; @@ -408,7 +408,7 @@ void avcodec_flush_buffers(AVCodecContext *avctx) av_fifo_reset(avci->pkt_props); av_frame_unref(avci->es.in_frame); - av_packet_unref(avci->ds.in_pkt); + av_packet_unref(avci->in_pkt); if (HAVE_THREADS && avctx->active_thread_type & FF_THREAD_FRAME) ff_thread_flush(avctx); @@ -473,7 +473,7 @@ av_cold int avcodec_close(AVCodecContext *avctx) } av_packet_free(&avci->last_pkt_props); - av_packet_free(&avci->ds.in_pkt); + av_packet_free(&avci->in_pkt); av_frame_free(&avci->es.in_frame); av_buffer_unref(&avci->pool); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ee8bc2b7c..ec1a0566a4 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2384,8 +2384,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 d8d8fef3b9..4f7a6b255c 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -142,7 +142,14 @@ int av_grow_packet(AVPacket *pkt, int grow_by) if (new_size + data_offset > pkt->buf->size || !av_buffer_is_writable(pkt->buf)) { - int ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); + int ret; + + // allocate slightly more than requested to avoid excessive + // reallocations + if (new_size + data_offset < INT_MAX - new_size/16) + new_size += new_size/16; + + ret = av_buffer_realloc(&pkt->buf, new_size + data_offset); if (ret < 0) { pkt->data = old_data; return ret; @@ -528,13 +535,12 @@ void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); } -int avpriv_packet_list_put(PacketList **packet_buffer, - PacketList **plast_pktl, +int avpriv_packet_list_put(PacketList *packet_buffer, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags) { - PacketList *pktl = av_malloc(sizeof(PacketList)); + PacketListEntry *pktl = av_malloc(sizeof(*pktl)); int ret; if (!pktl) @@ -558,44 +564,41 @@ int avpriv_packet_list_put(PacketList **packet_buffer, pktl->next = NULL; - if (*packet_buffer) - (*plast_pktl)->next = pktl; + if (packet_buffer->head) + packet_buffer->tail->next = pktl; else - *packet_buffer = pktl; + packet_buffer->head = pktl; /* Add the packet in the buffered packet list. */ - *plast_pktl = pktl; + packet_buffer->tail = pktl; return 0; } -int avpriv_packet_list_get(PacketList **pkt_buffer, - PacketList **pkt_buffer_end, +int avpriv_packet_list_get(PacketList *pkt_buffer, AVPacket *pkt) { - PacketList *pktl; - if (!*pkt_buffer) + PacketListEntry *pktl = pkt_buffer->head; + if (!pktl) return AVERROR(EAGAIN); - pktl = *pkt_buffer; *pkt = pktl->pkt; - *pkt_buffer = pktl->next; - if (!pktl->next) - *pkt_buffer_end = NULL; + pkt_buffer->head = pktl->next; + if (!pkt_buffer->head) + pkt_buffer->tail = NULL; av_freep(&pktl); return 0; } -void avpriv_packet_list_free(PacketList **pkt_buf, PacketList **pkt_buf_end) +void avpriv_packet_list_free(PacketList *pkt_buf) { - PacketList *tmp = *pkt_buf; + PacketListEntry *tmp = pkt_buf->head; while (tmp) { - PacketList *pktl = tmp; + PacketListEntry *pktl = tmp; tmp = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); } - *pkt_buf = NULL; - *pkt_buf_end = NULL; + pkt_buf->head = pkt_buf->tail = NULL; } int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type) diff --git a/libavcodec/binkaudio.c b/libavcodec/binkaudio.c index af8cb2809e..f808141ba5 100644 --- a/libavcodec/binkaudio.c +++ b/libavcodec/binkaudio.c @@ -140,9 +140,7 @@ static av_cold int decode_init(AVCodecContext *avctx) if (ret < 0) return ret; - s->pkt = av_packet_alloc(); - if (!s->pkt) - return AVERROR(ENOMEM); + s->pkt = avctx->internal->in_pkt; return 0; } @@ -277,8 +275,6 @@ static av_cold int decode_end(AVCodecContext *avctx) else if (CONFIG_BINKAUDIO_DCT_DECODER) ff_dct_end(&s->trans.dct); - av_packet_free(&s->pkt); - return 0; } @@ -337,6 +333,15 @@ fail: return ret; } +static void decode_flush(AVCodecContext *avctx) +{ + BinkAudioContext *const s = avctx->priv_data; + + /* s->pkt coincides with avctx->internal->in_pkt + * and is unreferenced generically when flushing. */ + s->first = 1; +} + const AVCodec ff_binkaudio_rdft_decoder = { .name = "binkaudio_rdft", .long_name = NULL_IF_CONFIG_SMALL("Bink Audio (RDFT)"), @@ -344,9 +349,10 @@ const AVCodec ff_binkaudio_rdft_decoder = { .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_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; @@ -357,8 +363,9 @@ const AVCodec ff_binkaudio_dct_decoder = { .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_DELAY | AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, }; diff --git a/libavcodec/bitpacked.c b/libavcodec/bitpacked_dec.c similarity index 96% rename from libavcodec/bitpacked.c rename to libavcodec/bitpacked_dec.c index 0440df9261..69fea9c366 100644 --- a/libavcodec/bitpacked.c +++ b/libavcodec/bitpacked_dec.c @@ -30,6 +30,7 @@ #include "internal.h" #include "get_bits.h" #include "libavutil/imgutils.h" +#include "thread.h" struct BitpackedContext { int (*decode)(AVCodecContext *avctx, AVFrame *frame, @@ -64,11 +65,12 @@ 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_get_buffer(avctx, frame, 0); + ret = ff_thread_get_buffer(avctx, &tframe, 0); if (ret < 0) return ret; @@ -129,13 +131,13 @@ static int bitpacked_decode(AVCodecContext *avctx, void *data, int *got_frame, AVFrame *frame = data; int res; - frame->pict_type = AV_PICTURE_TYPE_I; - frame->key_frame = 1; - res = bc->decode(avctx, frame, avpkt); if (res) return res; + frame->pict_type = AV_PICTURE_TYPE_I; + frame->key_frame = 1; + *got_frame = 1; return buf_size; @@ -149,7 +151,7 @@ const AVCodec ff_bitpacked_decoder = { .priv_data_size = sizeof(struct BitpackedContext), .init = bitpacked_init_decoder, .decode = bitpacked_decode, - .capabilities = AV_CODEC_CAP_EXPERIMENTAL, + .capabilities = AV_CODEC_CAP_FRAME_THREADS, .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 new file mode 100644 index 0000000000..6f540f1aed --- /dev/null +++ b/libavcodec/bitpacked_enc.c @@ -0,0 +1,118 @@ +/* + * bitpacked encoder + * + * 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 "avcodec.h" +#include "encode.h" +#include "internal.h" +#include "put_bits.h" +#include "libavutil/pixdesc.h" + +struct BitpackedContext { + int (*encode)(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame); +}; + +static int encode_yuv422p10(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame) +{ + const int buf_size = avctx->height * avctx->width * avctx->bits_per_coded_sample / 8; + int ret; + uint8_t *dst; + const uint16_t *y; + const uint16_t *u; + const uint16_t *v; + PutBitContext pb; + + ret = ff_get_encode_buffer(avctx, pkt, buf_size, 0); + if (ret < 0) { + av_log(avctx, AV_LOG_ERROR, "Error getting output packet.\n"); + return ret; + } + dst = pkt->data; + + init_put_bits(&pb, dst, buf_size); + + for (int i = 0; i < avctx->height; i++) { + y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]); + u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]); + v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]); + + for (int j = 0; j < avctx->width; j += 2) { + /* u, y0, v, y1 */ + put_bits(&pb, 10, av_clip_uintp2(*u++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*y++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*v++, 10)); + put_bits(&pb, 10, av_clip_uintp2(*y++, 10)); + } + } + flush_put_bits(&pb); + + return 0; +} + + +static av_cold int encode_init(AVCodecContext *avctx) +{ + struct BitpackedContext *s = avctx->priv_data; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); + + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "bitpacked needs even width\n"); + return AVERROR(EINVAL); + } + + avctx->bits_per_coded_sample = av_get_bits_per_pixel(desc); + avctx->bit_rate = ff_guess_coded_bitrate(avctx); + + if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) + s->encode = encode_yuv422p10; + else + return AVERROR(EINVAL); + + return 0; +} + +static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, + const AVFrame *frame, int *got_packet) +{ + struct BitpackedContext *s = avctx->priv_data; + int ret; + + ret = s->encode(avctx, pkt, frame); + if (ret) + return ret; + + *got_packet = 1; + 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, + .priv_data_size = sizeof(struct BitpackedContext), + .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, + AV_PIX_FMT_NONE }, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, +}; diff --git a/libavcodec/bitstream.c b/libavcodec/bitstream.c index 1f77cafae6..2dd0226614 100644 --- a/libavcodec/bitstream.c +++ b/libavcodec/bitstream.c @@ -142,21 +142,16 @@ typedef struct VLCcode { 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) +static int vlc_common_init(VLC *vlc, int nb_bits, int nb_codes, + VLCcode **buf, int flags) { - *vlc = vlc_arg; - (*vlc)->bits = nb_bits; + vlc->bits = nb_bits; + vlc->table_size = 0; 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; + vlc->table = NULL; + vlc->table_allocated = 0; } if (nb_codes > LOCALBUF_ELEMS) { *buf = av_malloc_array(nb_codes, sizeof(VLCcode)); @@ -191,8 +186,8 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, { int table_size, table_index, index, code_prefix, symbol, subtable_bits; int i, j, k, n, nb, inc; + VLC_TYPE (*table)[2]; 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); @@ -201,7 +196,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, 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]; + table = &vlc->table[table_index]; /* first pass: map codes and compute auxiliary table sizes */ for (i = 0; i < nb_codes; i++) { @@ -257,7 +252,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, if (index < 0) return index; /* note: realloc has been done, so reload tables */ - table = (volatile VLC_TYPE (*)[2])&vlc->table[table_index]; + table = &vlc->table[table_index]; table[j][0] = index; //code if (table[j][0] != index) { avpriv_request_sample(NULL, "strange codes"); @@ -276,7 +271,7 @@ static int build_table(VLC *vlc, int table_nb_bits, int nb_codes, } 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 flags, VLCcode localbuf[LOCALBUF_ELEMS]) { int ret = build_table(vlc, nb_bits, nb_codes, codes, flags); @@ -285,7 +280,6 @@ static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, !(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); @@ -320,7 +314,7 @@ static int vlc_common_end(VLC *vlc, int nb_bits, int nb_codes, VLCcode *codes, '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, +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, @@ -328,10 +322,8 @@ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, { 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); + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret; @@ -375,21 +367,19 @@ int ff_init_vlc_sparse(VLC *vlc_arg, int nb_bits, int nb_codes, nb_codes = j; return vlc_common_end(vlc, nb_bits, nb_codes, buf, - flags, vlc_arg, localbuf); + flags, localbuf); } -int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, +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; - 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); + ret = vlc_common_init(vlc, nb_bits, nb_codes, &buf, flags); if (ret < 0) return ret; @@ -420,8 +410,7 @@ int ff_init_vlc_from_lengths(VLC *vlc_arg, int nb_bits, int nb_codes, goto fail; } } - return vlc_common_end(vlc, nb_bits, j, buf, - flags, vlc_arg, localbuf); + return vlc_common_end(vlc, nb_bits, j, buf, flags, localbuf); fail: if (buf != localbuf) av_free(buf); diff --git a/libavcodec/cabac_functions.h b/libavcodec/cabac_functions.h index 46af921822..2f2d48a8f8 100644 --- a/libavcodec/cabac_functions.h +++ b/libavcodec/cabac_functions.h @@ -49,6 +49,9 @@ #if ARCH_MIPS # include "mips/cabac.h" #endif +#if ARCH_LOONGARCH64 +# include "loongarch/cabac.h" +#endif static const uint8_t * const ff_h264_norm_shift = ff_h264_cabac_tables + H264_NORM_SHIFT_OFFSET; static const uint8_t * const ff_h264_lps_range = ff_h264_cabac_tables + H264_LPS_RANGE_OFFSET; diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index 731d800666..a83babdf1e 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -68,7 +68,7 @@ typedef struct CDGraphicsContext { AVFrame *frame; int hscroll; int vscroll; - int transparency; + uint8_t alpha[CDG_PALETTE_SIZE]; int cleared; } CDGraphicsContext; @@ -79,7 +79,9 @@ static av_cold int cdg_decode_init(AVCodecContext *avctx) cc->frame = av_frame_alloc(); if (!cc->frame) return AVERROR(ENOMEM); - cc->transparency = -1; + + for (int i = 0; i < CDG_PALETTE_SIZE; i++) + cc->alpha[i] = 0xFFU; avctx->pix_fmt = AV_PIX_FMT_PAL8; return ff_set_dimensions(avctx, CDG_FULL_WIDTH, CDG_FULL_HEIGHT); @@ -120,9 +122,7 @@ static void cdg_load_palette(CDGraphicsContext *cc, uint8_t *data, int low) r = ((color >> 8) & 0x000F) * 17; g = ((color >> 4) & 0x000F) * 17; b = ((color ) & 0x000F) * 17; - palette[i + array_offset] = 0xFFU << 24 | r << 16 | g << 8 | b; - if (cc->transparency >= 0) - palette[cc->transparency] &= 0xFFFFFF; + palette[i + array_offset] = (uint32_t)cc->alpha[i + array_offset] << 24 | r << 16 | g << 8 | b; } cc->frame->palette_has_changed = 1; } @@ -218,7 +218,7 @@ static void cdg_scroll(CDGraphicsContext *cc, uint8_t *data, /// find the difference and save the offset for cdg_tile_block usage hinc = h_off - cc->hscroll; - vinc = v_off - cc->vscroll; + vinc = cc->vscroll - v_off; cc->hscroll = h_off; cc->vscroll = v_off; @@ -346,7 +346,8 @@ static int cdg_decode_frame(AVCodecContext *avctx, return ret; break; case CDG_INST_TRANSPARENT_COL: - cc->transparency = cdg_data[0] & 0xF; + for (int i = 0; i < CDG_PALETTE_SIZE; i++) + cc->alpha[i] = 255 - ((cdg_data[i] & 0x3f) << 2); break; default: break; diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c index edb553f0db..0574b125d7 100644 --- a/libavcodec/cinepakenc.c +++ b/libavcodec/cinepakenc.c @@ -705,7 +705,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], int entry_size = s->pix_fmt == AV_PIX_FMT_RGB24 ? 6 : 4; int *codebook = v1mode ? info->v1_codebook : info->v4_codebook; int size = v1mode ? info->v1_size : info->v4_size; - int64_t total_error = 0; uint8_t vq_pict_buf[(MB_AREA * 3) / 2]; uint8_t *sub_data[4], *vq_data[4]; int sub_linesize[4], vq_linesize[4]; @@ -795,7 +794,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], mb->v1_error = compute_mb_distortion(s, sub_data, sub_linesize, vq_data, vq_linesize); - total_error += mb->v1_error; } else { for (k = 0; k < 4; k++) mb->v4_vector[k] = s->codebook_closest[i + k]; @@ -805,7 +803,6 @@ static int quantize(CinepakEncContext *s, int h, uint8_t *data[4], mb->v4_error = compute_mb_distortion(s, sub_data, sub_linesize, vq_data, vq_linesize); - total_error += mb->v4_error; } i += v1mode ? 1 : 4; } diff --git a/libavcodec/crystalhd.c b/libavcodec/crystalhd.c index 0238ab7378..9202a16a77 100644 --- a/libavcodec/crystalhd.c +++ b/libavcodec/crystalhd.c @@ -90,6 +90,9 @@ typedef struct OpaqueList { typedef struct { AVClass *av_class; AVCodecContext *avctx; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; HANDLE dev; uint8_t is_70012; @@ -328,6 +331,7 @@ static av_cold int init(AVCodecContext *avctx) /* Initialize the library */ priv = avctx->priv_data; priv->avctx = avctx; + priv->pkt = avctx->internal->in_pkt; priv->draining = 0; subtype = id2subtype(priv, avctx->codec->id); @@ -703,19 +707,19 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) BC_DTS_STATUS decoder_status = { 0, }; CopyRet rec_ret; CHDContext *priv = avctx->priv_data; + AVPacket *const pkt = priv->pkt; HANDLE dev = priv->dev; int got_frame = 0; int ret = 0; - AVPacket pkt = {0}; av_log(avctx, AV_LOG_VERBOSE, "CrystalHD: receive_frame\n"); - ret = ff_decode_get_packet(avctx, &pkt); + ret = ff_decode_get_packet(avctx, pkt); if (ret < 0 && ret != AVERROR_EOF) { return ret; } - while (pkt.size > DtsTxFreeSize(dev)) { + while (pkt->size > DtsTxFreeSize(dev)) { /* * Block until there is space in the buffer for the next packet. * We assume that the hardware will make forward progress at this @@ -724,8 +728,8 @@ static int crystalhd_receive_frame(AVCodecContext *avctx, AVFrame *frame) av_log(avctx, AV_LOG_TRACE, "CrystalHD: Waiting for space in input buffer\n"); } - ret = crystalhd_decode_packet(avctx, &pkt); - av_packet_unref(&pkt); + ret = crystalhd_decode_packet(avctx, pkt); + av_packet_unref(pkt); // crystalhd_is_buffer_full() should avoid this. if (ret == AVERROR(EAGAIN)) { ret = AVERROR_EXTERNAL; diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index e157777c51..f03bbd8c4b 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -53,6 +53,10 @@ typedef struct CuvidContext CUvideodecoder cudecoder; CUvideoparser cuparser; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; + char *cu_gpu; int nb_surfaces; int drop_second_field; @@ -466,12 +470,12 @@ static int cuvid_output_frame(AVCodecContext *avctx, AVFrame *frame) } if (!cuvid_is_buffer_full(avctx)) { - AVPacket pkt = {0}; - ret = ff_decode_get_packet(avctx, &pkt); + AVPacket *const pkt = ctx->pkt; + ret = ff_decode_get_packet(avctx, pkt); if (ret < 0 && ret != AVERROR_EOF) return ret; - ret = cuvid_decode_packet(avctx, &pkt); - av_packet_unref(&pkt); + ret = cuvid_decode_packet(avctx, pkt); + av_packet_unref(pkt); // cuvid_is_buffer_full() should avoid this. if (ret == AVERROR(EAGAIN)) ret = AVERROR_EXTERNAL; @@ -797,6 +801,7 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) if (probe_desc && probe_desc->nb_components) probed_bit_depth = probe_desc->comp[0].depth; + ctx->pkt = avctx->internal->in_pkt; // Accelerated transcoding scenarios with 'ffmpeg' require that the // pix_fmt be set to AV_PIX_FMT_CUDA early. The sw_pix_fmt, and the // pix_fmt for non-accelerated transcoding, do not need to be correct diff --git a/libavcodec/dca.c b/libavcodec/dca.c index b2152524a5..fb359b2ff3 100644 --- a/libavcodec/dca.c +++ b/libavcodec/dca.c @@ -33,11 +33,6 @@ #include "get_bits.h" #include "put_bits.h" -const uint32_t avpriv_dca_sample_rates[16] = { - 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, - 12000, 24000, 48000, 96000, 192000 -}; - const uint32_t ff_dca_sampling_freqs[16] = { 8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200, 176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000, @@ -112,7 +107,7 @@ int ff_dca_parse_core_frame_header(DCACoreFrameHeader *h, GetBitContext *gb) return DCA_PARSE_ERROR_AMODE; h->sr_code = get_bits(gb, 4); - if (!avpriv_dca_sample_rates[h->sr_code]) + if (!ff_dca_sample_rates[h->sr_code]) return DCA_PARSE_ERROR_SAMPLE_RATE; h->br_code = get_bits(gb, 5); diff --git a/libavcodec/dca.h b/libavcodec/dca.h index e96c589c02..6be975fdfa 100644 --- a/libavcodec/dca.h +++ b/libavcodec/dca.h @@ -32,7 +32,6 @@ #include "libavutil/intreadwrite.h" #include "get_bits.h" -#include "internal.h" #define DCA_CORE_FRAME_HEADER_SIZE 18 @@ -195,8 +194,7 @@ enum DCADownMixType { DCA_DMIX_TYPE_COUNT }; -extern av_export_avcodec const uint32_t avpriv_dca_sample_rates[16]; - +extern const uint32_t ff_dca_sample_rates[16]; extern const uint32_t ff_dca_sampling_freqs[16]; extern const uint8_t ff_dca_freq_ranges[16]; extern const uint8_t ff_dca_bits_per_sample[8]; diff --git a/libavcodec/dca_core.c b/libavcodec/dca_core.c index f0a3c18d62..758e3447a6 100644 --- a/libavcodec/dca_core.c +++ b/libavcodec/dca_core.c @@ -129,7 +129,7 @@ static int parse_frame_header(DCACoreDecoder *s) s->npcmblocks = h.npcmblocks; s->frame_size = h.frame_size; s->audio_mode = h.audio_mode; - s->sample_rate = avpriv_dca_sample_rates[h.sr_code]; + s->sample_rate = ff_dca_sample_rates[h.sr_code]; s->bit_rate = ff_dca_bit_rates[h.br_code]; s->drc_present = h.drc_present; s->ts_present = h.ts_present; diff --git a/libavcodec/dca_parser.c b/libavcodec/dca_parser.c index 8b5c354312..3148397b7d 100644 --- a/libavcodec/dca_parser.c +++ b/libavcodec/dca_parser.c @@ -267,7 +267,7 @@ static int dca_parse_params(DCAParseContext *pc1, const uint8_t *buf, return AVERROR_INVALIDDATA; *duration = h.npcmblocks * DCA_PCMBLOCK_SAMPLES; - *sample_rate = avpriv_dca_sample_rates[h.sr_code]; + *sample_rate = ff_dca_sample_rates[h.sr_code]; if (*profile != FF_PROFILE_UNKNOWN) return 0; diff --git a/libavcodec/dca_sample_rate_tab.c b/libavcodec/dca_sample_rate_tab.c new file mode 100644 index 0000000000..16ee04b1d2 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dca_sample_rate_tab.h" diff --git a/libavcodec/dca_sample_rate_tab.h b/libavcodec/dca_sample_rate_tab.h new file mode 100644 index 0000000000..93d9a13663 --- /dev/null +++ b/libavcodec/dca_sample_rate_tab.h @@ -0,0 +1,33 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larssonb + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVCODEC_DCA_SAMPLE_RATE_TAB_H +#define AVCODEC_DCA_SAMPLE_RATE_TAB_H +#include + +const uint32_t ff_dca_sample_rates[16] = { + 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, + 12000, 24000, 48000, 96000, 192000 +}; +#endif diff --git a/libavcodec/decode.c b/libavcodec/decode.c index 294c040716..0912f86a14 100644 --- a/libavcodec/decode.c +++ b/libavcodec/decode.c @@ -296,8 +296,7 @@ static int64_t guess_correct_pts(AVCodecContext *ctx, static inline int decode_simple_internal(AVCodecContext *avctx, AVFrame *frame, int64_t *discarded_samples) { AVCodecInternal *avci = avctx->internal; - DecodeSimpleContext *ds = &avci->ds; - AVPacket *pkt = ds->in_pkt; + AVPacket *const pkt = avci->in_pkt; int got_frame, actual_got_frame; int ret; @@ -835,8 +834,14 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, sub->pts = av_rescale_q(avpkt->pts, avctx->pkt_timebase, AV_TIME_BASE_Q); ret = avctx->codec->decode(avctx, sub, got_sub_ptr, pkt); - av_assert1((ret >= 0) >= !!*got_sub_ptr && - !!*got_sub_ptr >= !!sub->num_rects); + if (pkt == avci->buffer_pkt) // did we recode? + av_packet_unref(avci->buffer_pkt); + if (ret < 0) { + *got_sub_ptr = 0; + avsubtitle_free(sub); + return ret; + } + av_assert1(!sub->num_rects || *got_sub_ptr); if (sub->num_rects && !sub->end_display_time && avpkt->duration && avctx->pkt_timebase.num) { @@ -857,16 +862,13 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, "Invalid UTF-8 in decoded subtitles text; " "maybe missing -sub_charenc option\n"); avsubtitle_free(sub); - ret = AVERROR_INVALIDDATA; - break; + *got_sub_ptr = 0; + return AVERROR_INVALIDDATA; } } if (*got_sub_ptr) avctx->frame_number++; - - if (pkt == avci->buffer_pkt) // did we recode? - av_packet_unref(avci->buffer_pkt); } return ret; @@ -1105,12 +1107,10 @@ int ff_get_format(AVCodecContext *avctx, const enum AVPixelFormat *fmt) avctx->sw_pix_fmt = fmt[n - 1]; } - choices = av_malloc_array(n + 1, sizeof(*choices)); + choices = av_memdup(fmt, (n + 1) * sizeof(*choices)); if (!choices) return AV_PIX_FMT_NONE; - memcpy(choices, fmt, (n + 1) * sizeof(*choices)); - for (;;) { // Remove the previous hwaccel, if there was one. hwaccel_uninit(avctx); diff --git a/libavcodec/dnxhd_parser.c b/libavcodec/dnxhd_parser.c index 4ba619c9bb..631ac83860 100644 --- a/libavcodec/dnxhd_parser.c +++ b/libavcodec/dnxhd_parser.c @@ -73,9 +73,9 @@ static int dnxhd_find_frame_end(DNXHDParserContext *dctx, if (cid <= 0) continue; - remaining = avpriv_dnxhd_get_frame_size(cid); + remaining = ff_dnxhd_get_frame_size(cid); if (remaining <= 0) { - remaining = avpriv_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h); + remaining = ff_dnxhd_get_hr_frame_size(cid, dctx->w, dctx->h); if (remaining <= 0) continue; } diff --git a/libavcodec/dnxhddata.c b/libavcodec/dnxhddata.c index 3a69a0f501..cb3d4a4c72 100644 --- a/libavcodec/dnxhddata.c +++ b/libavcodec/dnxhddata.c @@ -1083,7 +1083,7 @@ const CIDEntry *ff_dnxhd_get_cid_table(int cid) return NULL; } -int avpriv_dnxhd_get_frame_size(int cid) +int ff_dnxhd_get_frame_size(int cid) { const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); if (!entry) @@ -1091,7 +1091,7 @@ int avpriv_dnxhd_get_frame_size(int cid) return entry->frame_size; } -int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h) +int ff_dnxhd_get_hr_frame_size(int cid, int w, int h) { const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); int result; @@ -1105,14 +1105,6 @@ int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h) return FFMAX(result, 8192); } -int avpriv_dnxhd_get_interlaced(int cid) -{ - const CIDEntry *entry = ff_dnxhd_get_cid_table(cid); - if (!entry) - return -1; - return entry->flags & DNXHD_INTERLACED ? 1 : 0; -} - static int dnxhd_find_hr_cid(AVCodecContext *avctx) { switch (avctx->profile) { diff --git a/libavcodec/dnxhddata.h b/libavcodec/dnxhddata.h index 898079cffc..861faca4ca 100644 --- a/libavcodec/dnxhddata.h +++ b/libavcodec/dnxhddata.h @@ -88,8 +88,7 @@ static av_always_inline uint64_t ff_dnxhd_parse_header_prefix(const uint8_t *buf return ff_dnxhd_check_header_prefix(prefix); } -int avpriv_dnxhd_get_frame_size(int cid); -int avpriv_dnxhd_get_hr_frame_size(int cid, int w, int h); -int avpriv_dnxhd_get_interlaced(int cid); +int ff_dnxhd_get_frame_size(int cid); +int ff_dnxhd_get_hr_frame_size(int cid, int w, int h); #endif /* AVCODEC_DNXHDDATA_H */ diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c index ebfb85341d..ca67964330 100644 --- a/libavcodec/dnxhdenc.c +++ b/libavcodec/dnxhdenc.c @@ -463,7 +463,7 @@ static av_cold int dnxhd_encode_init(AVCodecContext *avctx) ctx->m.mb_num = ctx->m.mb_height * ctx->m.mb_width; if (ctx->cid_table->frame_size == DNXHD_VARIABLE) { - ctx->frame_size = avpriv_dnxhd_get_hr_frame_size(ctx->cid, + ctx->frame_size = ff_dnxhd_get_hr_frame_size(ctx->cid, avctx->width, avctx->height); av_assert0(ctx->frame_size >= 0); ctx->coding_unit_size = ctx->frame_size; diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c new file mode 100644 index 0000000000..a87562c8a3 --- /dev/null +++ b/libavcodec/dovi_rpu.c @@ -0,0 +1,449 @@ +/* + * Dolby Vision RPU decoder + * + * Copyright (C) 2021 Jan Ekström + * Copyright (C) 2021 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/buffer.h" + +#include "dovi_rpu.h" +#include "golomb.h" +#include "get_bits.h" + +enum { + RPU_COEFF_FIXED = 0, + RPU_COEFF_FLOAT = 1, +}; + +/** + * Private contents of vdr_ref. + */ +typedef struct DOVIVdrRef { + AVDOVIDataMapping mapping; + AVDOVIColorMetadata color; +} DOVIVdrRef; + +void ff_dovi_ctx_unref(DOVIContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + }; +} + +void ff_dovi_ctx_flush(DOVIContext *s) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr_ref); i++) + av_buffer_unref(&s->vdr_ref[i]); + + *s = (DOVIContext) { + .logctx = s->logctx, + .dv_profile = s->dv_profile, + }; +} + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0) +{ + int ret; + s->logctx = s0->logctx; + s->mapping = s0->mapping; + s->color = s0->color; + s->dv_profile = s0->dv_profile; + for (int i = 0; i < DOVI_MAX_DM_ID; i++) { + if ((ret = av_buffer_replace(&s->vdr_ref[i], s0->vdr_ref[i])) < 0) + goto fail; + } + + return 0; + +fail: + ff_dovi_ctx_unref(s); + return ret; +} + +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg) +{ + if (!cfg) + return; + + s->dv_profile = cfg->dv_profile; +} + +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame) +{ + AVFrameSideData *sd; + AVBufferRef *buf; + AVDOVIMetadata *dovi; + size_t dovi_size; + + if (!s->mapping || !s->color) + return 0; /* incomplete dovi metadata */ + + dovi = av_dovi_metadata_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + buf = av_buffer_create((uint8_t *) dovi, dovi_size, NULL, NULL, 0); + if (!buf) { + av_free(dovi); + return AVERROR(ENOMEM); + } + + sd = av_frame_new_side_data_from_buf(frame, AV_FRAME_DATA_DOVI_METADATA, buf); + if (!sd) { + av_buffer_unref(&buf); + return AVERROR(ENOMEM); + } + + /* Copy only the parts of these structs known to us at compiler-time. */ +#define COPY(t, a, b, last) memcpy(a, b, offsetof(t, last) + sizeof((b)->last)) + COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, disable_residual_flag); + COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq[2].linear_deadzone_threshold); + COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal); + return 0; +} + +static int guess_profile(const AVDOVIRpuDataHeader *hdr) +{ + switch (hdr->vdr_rpu_profile) { + case 0: + if (hdr->bl_video_full_range_flag) + return 5; + break; + case 1: + if (hdr->el_spatial_resampling_filter_flag && !hdr->disable_residual_flag) { + if (hdr->vdr_bit_depth == 12) { + return 7; + } else { + return 4; + } + } else { + return 8; + } + } + + return 0; /* unknown */ +} + +static inline uint64_t get_ue_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + uint64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + ipart = get_ue_golomb_long(gb); + fpart.u32 = get_bits_long(gb, hdr->coef_log2_denom); + return (ipart << hdr->coef_log2_denom) + fpart.u32; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +static inline int64_t get_se_coef(GetBitContext *gb, const AVDOVIRpuDataHeader *hdr) +{ + int64_t ipart; + union { uint32_t u32; float f32; } fpart; + + switch (hdr->coef_data_type) { + 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; + + case RPU_COEFF_FLOAT: + fpart.u32 = get_bits_long(gb, 32); + return fpart.f32 * (1 << hdr->coef_log2_denom); + } + + return 0; /* unreachable */ +} + +#define VALIDATE(VAR, MIN, MAX) \ + do { \ + if (VAR < MIN || VAR > MAX) { \ + av_log(s->logctx, AV_LOG_ERROR, "RPU validation failed: " \ + #MIN" <= "#VAR" = %d <= "#MAX"\n", (int) VAR); \ + goto fail; \ + } \ + } while (0) + +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) +{ + AVDOVIRpuDataHeader *hdr = &s->header; + GetBitContext *gb = &(GetBitContext){0}; + DOVIVdrRef *vdr; + int ret; + + uint8_t nal_prefix; + uint8_t rpu_type; + uint8_t vdr_seq_info_present; + uint8_t vdr_dm_metadata_present; + uint8_t use_prev_vdr_rpu; + uint8_t use_nlq; + uint8_t profile; + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) + return ret; + + /* RPU header, common values */ + nal_prefix = get_bits(gb, 8); + VALIDATE(nal_prefix, 25, 25); + rpu_type = get_bits(gb, 6); + if (rpu_type != 2) { + av_log(s->logctx, AV_LOG_WARNING, "Unrecognized RPU type " + "%"PRIu8", ignoring\n", rpu_type); + return 0; + } + + hdr->rpu_type = rpu_type; + hdr->rpu_format = get_bits(gb, 11); + + /* Values specific to RPU type 2 */ + hdr->vdr_rpu_profile = get_bits(gb, 4); + hdr->vdr_rpu_level = get_bits(gb, 4); + + vdr_seq_info_present = get_bits1(gb); + if (vdr_seq_info_present) { + hdr->chroma_resampling_explicit_filter_flag = get_bits1(gb); + hdr->coef_data_type = get_bits(gb, 2); + VALIDATE(hdr->coef_data_type, RPU_COEFF_FIXED, RPU_COEFF_FLOAT); + switch (hdr->coef_data_type) { + case RPU_COEFF_FIXED: + hdr->coef_log2_denom = get_ue_golomb(gb); + VALIDATE(hdr->coef_log2_denom, 13, 32); + break; + case RPU_COEFF_FLOAT: + hdr->coef_log2_denom = 32; /* arbitrary, choose maximum precision */ + break; + } + + hdr->vdr_rpu_normalized_idc = get_bits(gb, 2); + hdr->bl_video_full_range_flag = get_bits1(gb); + + if ((hdr->rpu_format & 0x700) == 0) { + int bl_bit_depth_minus8 = get_ue_golomb_31(gb); + int el_bit_depth_minus8 = get_ue_golomb_31(gb); + int vdr_bit_depth_minus8 = get_ue_golomb_31(gb); + VALIDATE(bl_bit_depth_minus8, 0, 8); + VALIDATE(el_bit_depth_minus8, 0, 8); + VALIDATE(vdr_bit_depth_minus8, 0, 8); + hdr->bl_bit_depth = bl_bit_depth_minus8 + 8; + hdr->el_bit_depth = el_bit_depth_minus8 + 8; + hdr->vdr_bit_depth = vdr_bit_depth_minus8 + 8; + hdr->spatial_resampling_filter_flag = get_bits1(gb); + skip_bits(gb, 3); /* reserved_zero_3bits */ + hdr->el_spatial_resampling_filter_flag = get_bits1(gb); + hdr->disable_residual_flag = get_bits1(gb); + } + } + + if (!hdr->bl_bit_depth) { + av_log(s->logctx, AV_LOG_ERROR, "Missing RPU VDR sequence info?\n"); + goto fail; + } + + vdr_dm_metadata_present = get_bits1(gb); + use_prev_vdr_rpu = get_bits1(gb); + use_nlq = (hdr->rpu_format & 0x700) == 0 && !hdr->disable_residual_flag; + + profile = s->dv_profile ? s->dv_profile : guess_profile(hdr); + if (profile == 5 && use_nlq) { + av_log(s->logctx, AV_LOG_ERROR, "Profile 5 RPUs should not use NLQ\n"); + goto fail; + } + + if (use_prev_vdr_rpu) { + int prev_vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(prev_vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[prev_vdr_rpu_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU ID: %u\n", + prev_vdr_rpu_id); + goto fail; + } + vdr = (DOVIVdrRef *) s->vdr_ref[prev_vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + } else { + int vdr_rpu_id = get_ue_golomb_31(gb); + VALIDATE(vdr_rpu_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[vdr_rpu_id]) { + s->vdr_ref[vdr_rpu_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[vdr_rpu_id]) + return AVERROR(ENOMEM); + } + + vdr = (DOVIVdrRef *) s->vdr_ref[vdr_rpu_id]->data; + s->mapping = &vdr->mapping; + + vdr->mapping.vdr_rpu_id = vdr_rpu_id; + vdr->mapping.mapping_color_space = get_ue_golomb_31(gb); + vdr->mapping.mapping_chroma_format_idc = get_ue_golomb_31(gb); + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + int num_pivots_minus_2 = get_ue_golomb_31(gb); + int pivot = 0; + + VALIDATE(num_pivots_minus_2, 0, AV_DOVI_MAX_PIECES - 1); + curve->num_pivots = num_pivots_minus_2 + 2; + for (int i = 0; i < curve->num_pivots; i++) { + pivot += get_bits(gb, hdr->bl_bit_depth); + curve->pivots[i] = av_clip_uint16(pivot); + } + } + + if (use_nlq) { + vdr->mapping.nlq_method_idc = get_bits(gb, 3); + /** + * The patent mentions another legal value, NLQ_MU_LAW, but it's + * not documented anywhere how to parse or apply that type of NLQ. + */ + VALIDATE(vdr->mapping.nlq_method_idc, 0, AV_DOVI_NLQ_LINEAR_DZ); + } else { + vdr->mapping.nlq_method_idc = AV_DOVI_NLQ_NONE; + } + + vdr->mapping.num_x_partitions = get_ue_golomb_long(gb) + 1; + vdr->mapping.num_y_partitions = get_ue_golomb_long(gb) + 1; + /* End of rpu_data_header(), start of vdr_rpu_data_payload() */ + + for (int c = 0; c < 3; c++) { + AVDOVIReshapingCurve *curve = &vdr->mapping.curves[c]; + for (int i = 0; i < curve->num_pivots - 1; i++) { + int mapping_idc = get_ue_golomb_31(gb); + VALIDATE(mapping_idc, 0, 1); + curve->mapping_idc[i] = mapping_idc; + switch (mapping_idc) { + case AV_DOVI_MAPPING_POLYNOMIAL: { + int poly_order_minus1 = get_ue_golomb_31(gb); + VALIDATE(poly_order_minus1, 0, 1); + curve->poly_order[i] = poly_order_minus1 + 1; + if (poly_order_minus1 == 0) { + int linear_interp_flag = get_bits1(gb); + if (linear_interp_flag) { + /* lack of documentation/samples */ + avpriv_request_sample(s->logctx, "Dolby Vision " + "linear interpolation"); + ff_dovi_ctx_unref(s); + return AVERROR_PATCHWELCOME; + } + } + for (int k = 0; k <= curve->poly_order[i]; k++) + curve->poly_coef[i][k] = get_se_coef(gb, hdr); + break; + } + case AV_DOVI_MAPPING_MMR: { + int mmr_order_minus1 = get_bits(gb, 2); + VALIDATE(mmr_order_minus1, 0, 2); + curve->mmr_order[i] = mmr_order_minus1 + 1; + curve->mmr_constant[i] = get_se_coef(gb, hdr); + for (int j = 0; j < curve->mmr_order[i]; j++) { + for (int k = 0; k < 7; k++) + curve->mmr_coef[i][j][k] = get_se_coef(gb, hdr); + } + break; + } + } + } + } + + if (use_nlq) { + for (int c = 0; c < 3; c++) { + AVDOVINLQParams *nlq = &vdr->mapping.nlq[c]; + nlq->nlq_offset = get_bits(gb, hdr->el_bit_depth); + nlq->vdr_in_max = get_ue_coef(gb, hdr); + switch (vdr->mapping.nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + nlq->linear_deadzone_slope = get_ue_coef(gb, hdr); + nlq->linear_deadzone_threshold = get_ue_coef(gb, hdr); + break; + } + } + } + } + + if (vdr_dm_metadata_present) { + AVDOVIColorMetadata *color; + int affected_dm_id = get_ue_golomb_31(gb); + int current_dm_id = get_ue_golomb_31(gb); + VALIDATE(affected_dm_id, 0, DOVI_MAX_DM_ID); + VALIDATE(current_dm_id, 0, DOVI_MAX_DM_ID); + if (!s->vdr_ref[affected_dm_id]) { + s->vdr_ref[affected_dm_id] = av_buffer_allocz(sizeof(DOVIVdrRef)); + if (!s->vdr_ref[affected_dm_id]) + return AVERROR(ENOMEM); + } + + if (!s->vdr_ref[current_dm_id]) { + av_log(s->logctx, AV_LOG_ERROR, "Unknown previous RPU DM ID: %u\n", + current_dm_id); + goto fail; + } + + /* Update current pointer based on current_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[current_dm_id]->data; + s->color = &vdr->color; + + /* Update values of affected_dm_id */ + vdr = (DOVIVdrRef *) s->vdr_ref[affected_dm_id]->data; + color = &vdr->color; + color->dm_metadata_id = affected_dm_id; + color->scene_refresh_flag = get_ue_golomb_31(gb); + for (int i = 0; i < 9; i++) + color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13); + for (int i = 0; i < 3; i++) { + int denom = profile == 4 ? (1 << 30) : (1 << 28); + unsigned offset = get_bits_long(gb, 32); + if (offset > INT_MAX) { + /* Ensure the result fits inside AVRational */ + offset >>= 1; + denom >>= 1; + } + color->ycc_to_rgb_offset[i] = av_make_q(offset, denom); + } + for (int i = 0; i < 9; i++) + color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14); + + color->signal_eotf = get_bits(gb, 16); + color->signal_eotf_param0 = get_bits(gb, 16); + color->signal_eotf_param1 = get_bits(gb, 16); + color->signal_eotf_param2 = get_bits_long(gb, 32); + color->signal_bit_depth = get_bits(gb, 5); + VALIDATE(color->signal_bit_depth, 8, 16); + color->signal_color_space = get_bits(gb, 2); + color->signal_chroma_format = get_bits(gb, 2); + color->signal_full_range_flag = get_bits(gb, 2); + color->source_min_pq = get_bits(gb, 12); + color->source_max_pq = get_bits(gb, 12); + color->source_diagonal = get_bits(gb, 10); + } + + /* FIXME: verify CRC32, requires implementation of AV_CRC_32_MPEG_2 */ + return 0; + +fail: + ff_dovi_ctx_unref(s); /* don't leak potentially invalid state */ + return AVERROR(EINVAL); +} diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h new file mode 100644 index 0000000000..f6ca5bbbc5 --- /dev/null +++ b/libavcodec/dovi_rpu.h @@ -0,0 +1,87 @@ +/* + * Dolby Vision RPU decoder + * + * Copyright (C) 2021 Jan Ekström + * Copyright (C) 2021 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 + */ + +#ifndef AVCODEC_DOVI_RPU_H +#define AVCODEC_DOVI_RPU_H + +#include "libavutil/dovi_meta.h" +#include "libavutil/frame.h" + +#define DOVI_MAX_DM_ID 15 +typedef struct DOVIContext { + void *logctx; + + /** + * Currently active RPU data header, updates on every dovi_rpu_parse(). + */ + AVDOVIRpuDataHeader header; + + /** + * Currently active data mappings, or NULL. Points into memory owned by the + * corresponding rpu/vdr_ref, which becomes invalid on the next call to + * dovi_rpu_parse. + */ + const AVDOVIDataMapping *mapping; + const AVDOVIColorMetadata *color; + + /** + * Private fields internal to dovi_rpu.c + */ + AVBufferRef *vdr_ref[DOVI_MAX_DM_ID+1]; + uint8_t dv_profile; + +} DOVIContext; + +int ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0); + +/** + * Completely reset a DOVIContext, preserving only logctx. + */ +void ff_dovi_ctx_unref(DOVIContext *s); + +/** + * Partially reset the internal state. Resets per-frame state while preserving + * fields parsed from the configuration record. + */ +void ff_dovi_ctx_flush(DOVIContext *s); + +/** + * Read the contents of an AVDOVIDecoderConfigurationRecord (usually provided + * by stream side data) and update internal state accordingly. + */ +void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord *cfg); + +/** + * Parse the contents of a Dovi RPU NAL and update the parsed values in the + * DOVIContext struct. + * + * Returns 0 or an error code. + */ +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size); + +/** + * Attach the decoded AVDOVIMetadata as side data to an AVFrame. + */ +int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame); + +#endif /* AVCODEC_DOVI_RPU_H */ diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index d192f3251d..bc741a1de6 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -823,14 +823,12 @@ static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_ou } memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(*clut_table)); - rect->data[0] = av_malloc(region->buf_size); + rect->data[0] = av_memdup(region->pbuf, region->buf_size); if (!rect->data[0]) { ret = AVERROR(ENOMEM); goto fail; } - memcpy(rect->data[0], region->pbuf, region->buf_size); - if ((clut == &default_clut && ctx->compute_clut < 0) || ctx->compute_clut == 1) { if (!region->has_computed_clut) { compute_default_clut(ctx, region->computed_clut, rect, rect->w, rect->h); @@ -1074,12 +1072,10 @@ static int dvbsub_parse_clut_segment(AVCodecContext *avctx, clut = get_clut(ctx, clut_id); if (!clut) { - clut = av_malloc(sizeof(*clut)); + clut = av_memdup(&default_clut, sizeof(*clut)); if (!clut) return AVERROR(ENOMEM); - memcpy(clut, &default_clut, sizeof(*clut)); - clut->id = clut_id; clut->version = -1; @@ -1719,8 +1715,6 @@ static int dvbsub_decode(AVCodecContext *avctx, end: if (ret < 0) { - *got_sub_ptr = 0; - avsubtitle_free(sub); return ret; } else { if (ctx->compute_edt == 1) diff --git a/libavcodec/dvdec.c b/libavcodec/dvdec.c index a7424fd1d4..b72a67d01c 100644 --- a/libavcodec/dvdec.c +++ b/libavcodec/dvdec.c @@ -399,8 +399,8 @@ static int dv_decode_video_segment(AVCodecContext *avctx, void *arg) int retried = 0; int sta; - av_assert1((((int) mb_bit_buffer) & 7) == 0); - av_assert1((((int) vs_bit_buffer) & 7) == 0); + av_assert1((((uintptr_t) mb_bit_buffer) & 7) == 0); + av_assert1((((uintptr_t) vs_bit_buffer) & 7) == 0); retry: diff --git a/libavcodec/eac3_data.c b/libavcodec/eac3_data.c index b159e1682f..2ef0e2053c 100644 --- a/libavcodec/eac3_data.c +++ b/libavcodec/eac3_data.c @@ -24,6 +24,8 @@ * Tables taken directly from the E-AC-3 spec. */ +#include + #include "eac3_data.h" #include "ac3.h" diff --git a/libavcodec/eatqi.c b/libavcodec/eatqi.c index 9beab58a83..8f502b3c56 100644 --- a/libavcodec/eatqi.c +++ b/libavcodec/eatqi.c @@ -37,6 +37,7 @@ #include "idctdsp.h" #include "internal.h" #include "mpeg12.h" +#include "mpeg12data.h" typedef struct TqiContext { AVCodecContext *avctx; diff --git a/libavcodec/encode.c b/libavcodec/encode.c index dd25cf999b..618be0573d 100644 --- a/libavcodec/encode.c +++ b/libavcodec/encode.c @@ -247,11 +247,8 @@ end: if (ret < 0 || !got_packet) av_packet_unref(avpkt); - if (frame) { - if (!ret) - avctx->frame_number++; + if (frame) av_frame_unref(frame); - } if (got_packet) // Encoders must always return ref-counted buffers. @@ -366,7 +363,7 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame if (avci->draining) return AVERROR_EOF; - if (avci->buffer_frame->data[0]) + if (avci->buffer_frame->buf[0]) return AVERROR(EAGAIN); if (!frame) { @@ -383,6 +380,8 @@ int attribute_align_arg avcodec_send_frame(AVCodecContext *avctx, const AVFrame return ret; } + avctx->frame_number++; + return 0; } diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index f13be7b918..91cd8a4444 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -476,8 +476,6 @@ static void guess_mv(ERContext *s) none_left = 1; changed = 1; for (pass = 0; (changed || pass < 2) && pass < 10; pass++) { - int score_sum = 0; - changed = 0; for (blocklist_index = 0; blocklist_index < blocklist_length; blocklist_index++) { const int mb_x = blocklist[blocklist_index][0]; @@ -668,7 +666,6 @@ skip_mean_and_median: best_pred = j; } } - score_sum += best_score; s->mv[0][0][0] = mv_predictor[best_pred][0]; s->mv[0][0][1] = mv_predictor[best_pred][1]; diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index a27eca5ae3..d8a0c39254 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -63,7 +63,7 @@ av_cold int ff_ffv1_common_init(AVCodecContext *avctx) return 0; } -av_cold int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs) +av_cold int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs) { int j, i; @@ -170,7 +170,7 @@ int ff_ffv1_allocate_initial_states(FFV1Context *f) return 0; } -void ff_ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs) +void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs) { int i, j; diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h index 473780c876..8ffe5ab433 100644 --- a/libavcodec/ffv1.h +++ b/libavcodec/ffv1.h @@ -139,11 +139,11 @@ typedef struct FFV1Context { } FFV1Context; int ff_ffv1_common_init(AVCodecContext *avctx); -int ff_ffv1_init_slice_state(FFV1Context *f, FFV1Context *fs); +int ff_ffv1_init_slice_state(const FFV1Context *f, FFV1Context *fs); int ff_ffv1_init_slices_state(FFV1Context *f); int ff_ffv1_init_slice_contexts(FFV1Context *f); int ff_ffv1_allocate_initial_states(FFV1Context *f); -void ff_ffv1_clear_slice_state(FFV1Context *f, FFV1Context *fs); +void ff_ffv1_clear_slice_state(const FFV1Context *f, FFV1Context *fs); int ff_ffv1_close(AVCodecContext *avctx); static av_always_inline int fold(int diff, int bits) diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c index 374546f4b3..810b2e18f0 100644 --- a/libavcodec/ffv1dec.c +++ b/libavcodec/ffv1dec.c @@ -161,7 +161,7 @@ static int decode_plane(FFV1Context *s, uint8_t *src, return 0; } -static int decode_slice_header(FFV1Context *f, FFV1Context *fs) +static int decode_slice_header(const FFV1Context *f, FFV1Context *fs) { RangeCoder *c = &fs->c; uint8_t state[CONTEXT_SIZE]; @@ -924,7 +924,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac fs->c.bytestream_end = buf_p + v; fs->avctx = avctx; - fs->cur = p; } avctx->execute(avctx, @@ -965,11 +964,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac } ff_thread_report_progress(&f->picture, INT_MAX, 0); - f->picture_number++; - if (f->last_picture.f) ff_thread_release_buffer(avctx, &f->last_picture); - f->cur = NULL; if ((ret = av_frame_ref(data, f->picture.f)) < 0) return ret; @@ -978,7 +974,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return buf_size; } -static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsrc) +static void copy_fields(FFV1Context *fsdst, const FFV1Context *fssrc, + const FFV1Context *fsrc) { fsdst->version = fsrc->version; fsdst->micro_version = fsrc->micro_version; @@ -995,7 +992,6 @@ static void copy_fields(FFV1Context *fsdst, FFV1Context *fssrc, FFV1Context *fsr fsdst->slice_damaged = fssrc->slice_damaged; fsdst->key_frame_ok = fsrc->key_frame_ok; - fsdst->bits_per_raw_sample = fsrc->bits_per_raw_sample; fsdst->packed_at_lsb = fsrc->packed_at_lsb; fsdst->slice_count = fsrc->slice_count; if (fsrc->version<3){ diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c index 69b9065343..d29f62bf56 100644 --- a/libavcodec/ffv1enc.c +++ b/libavcodec/ffv1enc.c @@ -36,8 +36,8 @@ #include "encode.h" #include "internal.h" #include "put_bits.h" +#include "put_golomb.h" #include "rangecoder.h" -#include "golomb.h" #include "mathops.h" #include "ffv1.h" diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 2c550507fc..cd9a2cb574 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" @@ -55,6 +54,15 @@ /** largest possible size of flac header */ #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 */ @@ -83,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 */ @@ -99,7 +107,7 @@ static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, uint8_t subframe_type; // header plus one byte from first subframe - init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8 + 8); + init_get_bits(&gb, buf, MAX_FRAME_VERIFY_SIZE * 8); if (ff_flac_decode_frame_header(avctx, &gb, fi, 127)) { return 0; } @@ -126,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. @@ -142,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; @@ -179,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) @@ -190,13 +209,115 @@ 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; uint8_t *header_buf; int size = 0; header_buf = flac_fifo_read_wrap(fpc, offset, - MAX_FRAME_HEADER_SIZE, + MAX_FRAME_VERIFY_SIZE + AV_INPUT_BUFFER_PADDING_SIZE, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) { @@ -262,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; @@ -276,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) { @@ -405,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); } } @@ -499,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; @@ -518,7 +639,6 @@ static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, &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; @@ -533,7 +653,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; } @@ -585,7 +705,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) @@ -619,7 +739,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) { @@ -633,8 +753,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 @@ -643,24 +763,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); @@ -688,14 +804,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; } } @@ -726,7 +843,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); @@ -741,11 +858,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); @@ -764,7 +883,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/flacenc.c b/libavcodec/flacenc.c index 595928927d..9f6f449323 100644 --- a/libavcodec/flacenc.c +++ b/libavcodec/flacenc.c @@ -30,7 +30,7 @@ #include "bswapdsp.h" #include "encode.h" #include "put_bits.h" -#include "golomb.h" +#include "put_golomb.h" #include "internal.h" #include "lpc.h" #include "flac.h" diff --git a/libavcodec/flvdec.c b/libavcodec/flvdec.c index 6258c1c0a7..2ddcf021fd 100644 --- a/libavcodec/flvdec.c +++ b/libavcodec/flvdec.c @@ -90,7 +90,6 @@ int ff_flv_decode_picture_header(MpegEncContext *s) s->h263_plus = 0; - s->unrestricted_mv = 1; s->h263_long_vectors = 0; /* PEI */ diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c index 614ef20243..158b399c40 100644 --- a/libavcodec/flvenc.c +++ b/libavcodec/flvenc.c @@ -19,7 +19,6 @@ */ #include "flv.h" -#include "h263.h" #include "h263data.h" #include "mpegvideo.h" #include "mpegvideodata.h" diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c index c9e8d11ab8..4c53838af5 100644 --- a/libavcodec/g2meet.c +++ b/libavcodec/g2meet.c @@ -164,20 +164,20 @@ static av_cold int jpg_init(AVCodecContext *avctx, JPGContext *c) { int ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[0], ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 0, avctx); + ret = ff_mjpeg_build_vlc(&c->dc_vlc[1], ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 0, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[0], ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 1, avctx); if (ret) return ret; - ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 1, avctx); + ret = ff_mjpeg_build_vlc(&c->ac_vlc[1], ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 1, avctx); if (ret) return ret; diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c index 2b3cccee09..2a8149b4cd 100644 --- a/libavcodec/g723_1enc.c +++ b/libavcodec/g723_1enc.c @@ -1116,10 +1116,9 @@ static int g723_1_encode_frame(AVCodecContext *avctx, AVPacket *avpkt, HFParam hf[4]; /* duplicate input */ - start = in = av_malloc(frame->nb_samples * sizeof(int16_t)); + start = in = av_memdup(frame->data[0], frame->nb_samples * sizeof(int16_t)); if (!in) return AVERROR(ENOMEM); - memcpy(in, frame->data[0], frame->nb_samples * sizeof(int16_t)); highpass_filter(in, &p->hpf_fir_mem, &p->hpf_iir_mem); diff --git a/libavcodec/gemdec.c b/libavcodec/gemdec.c index 2464dda8a7..fd14b22390 100644 --- a/libavcodec/gemdec.c +++ b/libavcodec/gemdec.c @@ -157,6 +157,26 @@ static int gem_decode_frame(AVCodecContext *avctx, if (header_size >= 11) tag = bytestream2_peek_be32(&gb); + if (tag == AV_RB32("STTT")) { + if (planes != 4) { + avpriv_request_sample(avctx, "STTT planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (tag == AV_RB32("TIMG")) { + if (planes != 15) { + avpriv_request_sample(avctx, "TIMG planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (tag == AV_RB32("XIMG")) { + if (planes != 1 && planes != 2 && planes != 4 && planes != 8 && planes != 16 && planes != 24 && planes != 32) { + avpriv_request_sample(avctx, "XIMG planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + } else if (planes != 1 && planes != 2 && planes != 3 && planes != 4 && planes != 8 && planes != 16 && planes != 24) { + avpriv_request_sample(avctx, "planes=%d", planes); + return AVERROR_PATCHWELCOME; + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; @@ -176,14 +196,12 @@ static int gem_decode_frame(AVCodecContext *avctx, palette[i] = 0xFF000000 | r << 16 | g << 8 | b; } } else { - avpriv_request_sample(avctx, "STTT planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (tag == AV_RB32("TIMG")) { bytestream2_skip(&gb, 4); if (planes != 15) { - avpriv_request_sample(avctx, "TIMG planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (tag == AV_RB32("XIMG")) { bytestream2_skip(&gb, 6); @@ -207,8 +225,7 @@ static int gem_decode_frame(AVCodecContext *avctx, row_width = avctx->width * pixel_size; put_lines = put_lines_bytes; } else { - avpriv_request_sample(avctx, "XIMG planes=%d", planes); - return AVERROR_PATCHWELCOME; + av_assert0(0); } } else if (planes == 1) { palette[0] = 0xFFFFFFFF; @@ -236,10 +253,8 @@ static int gem_decode_frame(AVCodecContext *avctx, planes = 1; row_width = avctx->width * pixel_size; put_lines = put_lines_bytes; - } else { - avpriv_request_sample(avctx, "planes=%d", planes); - return AVERROR_PATCHWELCOME; - } + } else + av_assert0(0); ret = av_reallocp_array(&avctx->priv_data, planes, row_width); if (ret < 0) diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 4d531cf805..164c2583b6 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/h261dec.c b/libavcodec/h261dec.c index 80ec1c8814..2fd8d94df1 100644 --- a/libavcodec/h261dec.c +++ b/libavcodec/h261dec.c @@ -31,7 +31,6 @@ #include "mpeg_er.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" #include "h261.h" #include "internal.h" diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c index 79f680f81d..af65c1f3b1 100644 --- a/libavcodec/h261enc.c +++ b/libavcodec/h261enc.c @@ -31,7 +31,6 @@ #include "avcodec.h" #include "mpegutils.h" #include "mpegvideo.h" -#include "h263.h" #include "h261.h" #include "mpegvideodata.h" diff --git a/libavcodec/h263.c b/libavcodec/h263.c index f8fba3c9f4..b30ffaf878 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 491f2e0aac..982e545491 100644 --- a/libavcodec/h263.h +++ b/libavcodec/h263.h @@ -74,8 +74,6 @@ 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); /** @@ -87,28 +85,22 @@ int ff_intel_h263_decode_picture_header(MpegEncContext *s); int ff_h263_decode_mb(MpegEncContext *s, int16_t block[6][64]); -/** - * Return the value of the 3-bit "source format" syntax element. - * This represents some standard picture dimensions or indicates that - * width&height are explicitly stored later. - */ -int av_const h263_get_picture_format(int width, int height); - 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 l, bit_size, code; + int bit_size, code, sign; if (val == 0) { - return ff_mvtab[0][1]; + return 1; /* ff_mvtab[0][1] */ } else { bit_size = f_code - 1; /* modulo encoding */ - l= INT_BIT - 6 - bit_size; - val = (val<>l; + val = sign_extend(val, 6 + bit_size); + sign = val >> 31; + val = (val ^ sign) - sign; /* val = FFABS(val) */ val--; code = (val >> bit_size) + 1; diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 2682a7f43a..ac48acf47a 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -83,13 +83,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: @@ -507,9 +505,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 +601,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; diff --git a/libavcodec/h2645_parse.c b/libavcodec/h2645_parse.c index 6fbe97ad4a..03780680c6 100644 --- a/libavcodec/h2645_parse.c +++ b/libavcodec/h2645_parse.c @@ -92,8 +92,7 @@ int ff_h2645_extract_rbsp(const uint8_t *src, int length, } else if (i > length) i = length; - nal->rbsp_buffer = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; - dst = nal->rbsp_buffer; + dst = &rbsp->rbsp_buffer[rbsp->rbsp_buffer_size]; memcpy(dst, src, i); si = di = i; diff --git a/libavcodec/h2645_parse.h b/libavcodec/h2645_parse.h index 20a9d355f2..787ce971ee 100644 --- a/libavcodec/h2645_parse.h +++ b/libavcodec/h2645_parse.h @@ -32,10 +32,8 @@ #define MAX_MBPAIR_SIZE (256*1024) // a tighter bound could be calculated if someone cares about a few bytes typedef struct H2645NAL { - uint8_t *rbsp_buffer; - - int size; const uint8_t *data; + int size; /** * Size, in bits, of just the data, excluding the stop bit and any trailing @@ -53,6 +51,11 @@ typedef struct H2645NAL { */ int type; + /** + * H.264 only, nal_ref_idc + */ + int ref_idc; + /** * HEVC only, nuh_temporal_id_plus_1 - 1 */ @@ -66,10 +69,6 @@ typedef struct H2645NAL { int skipped_bytes; int skipped_bytes_pos_size; int *skipped_bytes_pos; - /** - * H.264 only, nal_ref_idc - */ - int ref_idc; } H2645NAL; typedef struct H2645RBSP { diff --git a/libavcodec/h264_cabac.c b/libavcodec/h264_cabac.c index 973b3419c4..040fa0a257 100644 --- a/libavcodec/h264_cabac.c +++ b/libavcodec/h264_cabac.c @@ -42,6 +42,8 @@ #if ARCH_X86 #include "x86/h264_cabac.c" +#elif ARCH_LOONGARCH64 +#include "loongarch/h264_cabac.c" #endif /* Cabac pre state table */ diff --git a/libavcodec/h264_metadata_bsf.c b/libavcodec/h264_metadata_bsf.c index 452a8ec5dc..9df99cbae3 100644 --- a/libavcodec/h264_metadata_bsf.c +++ b/libavcodec/h264_metadata_bsf.c @@ -341,15 +341,24 @@ static int h264_metadata_handle_display_orientation(AVBSFContext *bsf, SEI_TYPE_DISPLAY_ORIENTATION, &message) == 0) { H264RawSEIDisplayOrientation *disp = message->payload; + double angle = disp->anticlockwise_rotation * 180.0 / 65536.0; int32_t *matrix; matrix = av_malloc(9 * sizeof(int32_t)); if (!matrix) return AVERROR(ENOMEM); - av_display_rotation_set(matrix, - disp->anticlockwise_rotation * - 180.0 / 65536.0); + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!disp->hor_flip) * (1 - 2 * !!disp->ver_flip); + + av_display_rotation_set(matrix, angle); av_display_matrix_flip(matrix, disp->hor_flip, disp->ver_flip); // If there are multiple display orientation messages in an @@ -617,7 +626,7 @@ static const AVOption h264_metadata_options[] = { OFFSET(chroma_sample_loc_type), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 6, FLAGS }, - { "tick_rate", "Set VUI tick rate (num_units_in_tick / time_scale)", + { "tick_rate", "Set VUI tick rate (time_scale / num_units_in_tick)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "fixed_frame_rate_flag", "Set VUI fixed frame rate flag", diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index fb678beef3..769946abfd 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -27,13 +27,10 @@ #include "cbs_h264.h" #include "h264.h" +#define NEW_GLOBAL_PIC_INIT_QP 26 typedef struct H264RedundantPPSContext { CBSBSFContext common; - - int global_pic_init_qp; - int current_pic_init_qp; - int extradata_pic_init_qp; } H264RedundantPPSContext; @@ -51,10 +48,8 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, return err; pps = unit->content; - // Record the current value of pic_init_qp in order to fix up - // following slices, then overwrite with the global value. - ctx->current_pic_init_qp = pps->pic_init_qp_minus26 + 26; - pps->pic_init_qp_minus26 = ctx->global_pic_init_qp - 26; + // Overwrite pic_init_qp with the global value. + pps->pic_init_qp_minus26 = NEW_GLOBAL_PIC_INIT_QP - 26; // Some PPSs have this set, so it must be set in all of them. // (Slices which do not use such a PPS on input will still have @@ -67,10 +62,13 @@ static int h264_redundant_pps_fixup_pps(H264RedundantPPSContext *ctx, static int h264_redundant_pps_fixup_slice(H264RedundantPPSContext *ctx, H264RawSliceHeader *slice) { - int qp; + const CodedBitstreamH264Context *const in = ctx->common.input->priv_data; + const H264RawPPS *const pps = in->pps[slice->pic_parameter_set_id]; - qp = ctx->current_pic_init_qp + slice->slice_qp_delta; - slice->slice_qp_delta = qp - ctx->global_pic_init_qp; + // We modified the PPS's qp value, now offset this by applying + // the negative offset to the slices. + slice->slice_qp_delta += pps->pic_init_qp_minus26 + - (NEW_GLOBAL_PIC_INIT_QP - 26); return 0; } @@ -111,12 +109,6 @@ static int h264_redundant_pps_update_fragment(AVBSFContext *bsf, return 0; } -static void h264_redundant_pps_flush(AVBSFContext *bsf) -{ - H264RedundantPPSContext *ctx = bsf->priv_data; - ctx->current_pic_init_qp = ctx->extradata_pic_init_qp; -} - static const CBSBSFType h264_redundant_pps_type = { .codec_id = AV_CODEC_ID_H264, .fragment_name = "access unit", @@ -126,10 +118,6 @@ static const CBSBSFType h264_redundant_pps_type = { static int h264_redundant_pps_init(AVBSFContext *bsf) { - H264RedundantPPSContext *ctx = bsf->priv_data; - - ctx->global_pic_init_qp = 26; - return ff_cbs_bsf_generic_init(bsf, &h264_redundant_pps_type); } @@ -141,7 +129,6 @@ const AVBitStreamFilter ff_h264_redundant_pps_bsf = { .name = "h264_redundant_pps", .priv_data_size = sizeof(H264RedundantPPSContext), .init = &h264_redundant_pps_init, - .flush = &h264_redundant_pps_flush, .close = &ff_cbs_bsf_generic_close, .filter = &ff_cbs_bsf_generic_filter, .codec_ids = h264_redundant_pps_codec_ids, diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 89ea16a57f..4833282191 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -811,6 +811,10 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) *fmt++ = AV_PIX_FMT_YUV420P9; break; case 10: +#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + if (h->avctx->colorspace != AVCOL_SPC_RGB) + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) { *fmt++ = AV_PIX_FMT_GBRP10; @@ -849,6 +853,10 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #endif #if CONFIG_H264_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL + if (h->avctx->colorspace != AVCOL_SPC_RGB) + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif if (CHROMA444(h)) { if (h->avctx->colorspace == AVCOL_SPC_RGB) @@ -872,9 +880,6 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) #endif #if CONFIG_H264_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; -#endif -#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL - *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif if (h->avctx->codec->pix_fmts) choices = h->avctx->codec->pix_fmts; @@ -993,7 +998,7 @@ 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); @@ -1300,6 +1305,15 @@ static int h264_export_frame_props(H264Context *h) AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (rotation) { + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!o->hflip) * (1 - 2 * !!o->vflip); av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, o->hflip, o->vflip); @@ -2154,9 +2168,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" : "", diff --git a/libavcodec/h264chroma.c b/libavcodec/h264chroma.c index c2f1f30f5a..0ae6c793e1 100644 --- a/libavcodec/h264chroma.c +++ b/libavcodec/h264chroma.c @@ -56,4 +56,6 @@ av_cold void ff_h264chroma_init(H264ChromaContext *c, int bit_depth) 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); } diff --git a/libavcodec/h264chroma.h b/libavcodec/h264chroma.h index 5c89fd12df..3259b4935f 100644 --- a/libavcodec/h264chroma.h +++ b/libavcodec/h264chroma.h @@ -36,5 +36,6 @@ void ff_h264chroma_init_arm(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_ppc(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_x86(H264ChromaContext *c, int bit_depth); void ff_h264chroma_init_mips(H264ChromaContext *c, int bit_depth); +void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth); #endif /* AVCODEC_H264CHROMA_H */ diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c index 6a5bf51f5d..7f10026340 100644 --- a/libavcodec/h264dec.c +++ b/libavcodec/h264dec.c @@ -939,7 +939,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, diff --git a/libavcodec/h264dsp.c b/libavcodec/h264dsp.c index e76932b565..f97ac2823c 100644 --- a/libavcodec/h264dsp.c +++ b/libavcodec/h264dsp.c @@ -157,4 +157,5 @@ av_cold void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, 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); } diff --git a/libavcodec/h264dsp.h b/libavcodec/h264dsp.h index 850d4471fd..e0880c4d88 100644 --- a/libavcodec/h264dsp.h +++ b/libavcodec/h264dsp.h @@ -129,5 +129,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); void ff_h264dsp_init_mips(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); +void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc); #endif /* AVCODEC_H264DSP_H */ diff --git a/libavcodec/h264pred.c b/libavcodec/h264pred.c index b0fec71f25..d83ca37a69 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,6 +553,38 @@ 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; } @@ -602,4 +596,6 @@ av_cold void ff_h264_pred_init(H264PredContext *h, int codec_id, 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); } diff --git a/libavcodec/h264pred.h b/libavcodec/h264pred.h index 2863dc9bd1..4583052dfe 100644 --- a/libavcodec/h264pred.h +++ b/libavcodec/h264pred.h @@ -122,5 +122,7 @@ void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); void ff_h264_pred_init_mips(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); +void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, + const int bit_depth, const int chroma_format_idc); #endif /* AVCODEC_H264PRED_H */ diff --git a/libavcodec/h264pred_template.c b/libavcodec/h264pred_template.c index 2b30fff70f..b5bc942a5e 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 50e82e23b0..535ebd25b4 100644 --- a/libavcodec/h264qpel.c +++ b/libavcodec/h264qpel.c @@ -106,4 +106,6 @@ av_cold void ff_h264qpel_init(H264QpelContext *c, int bit_depth) 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); } diff --git a/libavcodec/h264qpel.h b/libavcodec/h264qpel.h index 7c57ad001c..0259e8de23 100644 --- a/libavcodec/h264qpel.h +++ b/libavcodec/h264qpel.h @@ -36,5 +36,6 @@ void ff_h264qpel_init_arm(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_ppc(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_x86(H264QpelContext *c, int bit_depth); void ff_h264qpel_init_mips(H264QpelContext *c, int bit_depth); +void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth); #endif /* AVCODEC_H264QPEL_H */ diff --git a/libavcodec/h265_metadata_bsf.c b/libavcodec/h265_metadata_bsf.c index d841839762..e5f70cfbc1 100644 --- a/libavcodec/h265_metadata_bsf.c +++ b/libavcodec/h265_metadata_bsf.c @@ -439,7 +439,7 @@ static const AVOption h265_metadata_options[] = { { .i64 = -1 }, -1, 6, FLAGS }, { "tick_rate", - "Set VPS and VUI tick rate (num_units_in_tick / time_scale)", + "Set VPS and VUI tick rate (time_scale / num_units_in_tick)", OFFSET(tick_rate), AV_OPT_TYPE_RATIONAL, { .dbl = 0.0 }, 0, UINT_MAX, FLAGS }, { "num_ticks_poc_diff_one", diff --git a/libavcodec/hevc_ps_enc.c b/libavcodec/hevc_ps_enc.c index 47f252dd2c..72641b2ffb 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_sei.c b/libavcodec/hevc_sei.c index 29d0346287..7fd822652e 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -181,9 +181,6 @@ static int decode_registered_user_data_closed_caption(HEVCSEIA53Caption *s, GetB { int ret; - if (size < 3) - return AVERROR_INVALIDDATA; - ret = ff_parse_a53_cc(&s->buf_ref, gb->buffer + get_bits_count(gb) / 8, size); if (ret < 0) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 246ffd7d80..8d7a4f7147 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -451,16 +451,25 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; +#endif +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; case AV_PIX_FMT_YUV422P: case AV_PIX_FMT_YUV422P10LE: #if CONFIG_HEVC_VAAPI_HWACCEL *fmt++ = AV_PIX_FMT_VAAPI; +#endif +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; - case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P10: +#if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL + *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif + case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P12: #if CONFIG_HEVC_VDPAU_HWACCEL *fmt++ = AV_PIX_FMT_VDPAU; @@ -2714,6 +2723,7 @@ error: static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; + int ret; if (s->sei.frame_packing.present && s->sei.frame_packing.arrangement_type >= 3 && @@ -2760,6 +2770,16 @@ static int set_side_data(HEVCContext *s) if (!rotation) return AVERROR(ENOMEM); + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!s->sei.display_orientation.hflip) + * (1 - 2 * !!s->sei.display_orientation.vflip); av_display_rotation_set((int32_t *)rotation->data, angle); av_display_matrix_flip((int32_t *)rotation->data, s->sei.display_orientation.hflip, @@ -2950,6 +2970,17 @@ static int set_side_data(HEVCContext *s) } } + if (s->rpu_buf) { + AVFrameSideData *rpu = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DOVI_RPU_BUFFER, s->rpu_buf); + if (!rpu) + return AVERROR(ENOMEM); + + s->rpu_buf = NULL; + } + + if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) + return ret; + return 0; } @@ -3223,6 +3254,7 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) break; case HEVC_NAL_AUD: case HEVC_NAL_FD_NUT: + case HEVC_NAL_UNSPEC62: break; default: av_log(s->avctx, AV_LOG_INFO, @@ -3269,6 +3301,36 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) } } + /* + * Check for RPU delimiter. + * + * Dolby Vision RPUs masquerade as unregistered NALs of type 62. + * + * We have to do this check here an create the rpu buffer, since RPUs are appended + * to the end of an AU; they are the last non-EOB/EOS NAL in the AU. + */ + if (s->pkt.nb_nals > 1 && s->pkt.nals[s->pkt.nb_nals - 1].type == HEVC_NAL_UNSPEC62 && + s->pkt.nals[s->pkt.nb_nals - 1].size > 2 && !s->pkt.nals[s->pkt.nb_nals - 1].nuh_layer_id + && !s->pkt.nals[s->pkt.nb_nals - 1].temporal_id) { + H2645NAL *nal = &s->pkt.nals[s->pkt.nb_nals - 1]; + if (s->rpu_buf) { + av_buffer_unref(&s->rpu_buf); + av_log(s->avctx, AV_LOG_WARNING, "Multiple Dolby Vision RPUs found in one AU. Skipping previous.\n"); + } + + s->rpu_buf = av_buffer_alloc(nal->raw_size - 2); + if (!s->rpu_buf) + return AVERROR(ENOMEM); + memcpy(s->rpu_buf->data, nal->raw_data + 2, nal->raw_size - 2); + + ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2); + if (ret < 0) { + av_buffer_unref(&s->rpu_buf); + av_log(s->avctx, AV_LOG_WARNING, "Error parsing DOVI NAL unit.\n"); + /* ignore */ + } + } + /* decode the NAL units */ for (i = 0; i < s->pkt.nb_nals; i++) { H2645NAL *nal = &s->pkt.nals[i]; @@ -3399,8 +3461,8 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, AVPacket *avpkt) { int ret; - size_t new_extradata_size; - uint8_t *new_extradata; + uint8_t *sd; + size_t sd_size; HEVCContext *s = avctx->priv_data; if (!avpkt->size) { @@ -3412,14 +3474,17 @@ static int hevc_decode_frame(AVCodecContext *avctx, void *data, int *got_output, return 0; } - new_extradata = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, - &new_extradata_size); - if (new_extradata && new_extradata_size > 0) { - ret = hevc_decode_extradata(s, new_extradata, new_extradata_size, 0); + sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_NEW_EXTRADATA, &sd_size); + if (sd && sd_size > 0) { + ret = hevc_decode_extradata(s, sd, sd_size, 0); if (ret < 0) return ret; } + sd = av_packet_get_side_data(avpkt, AV_PKT_DATA_DOVI_CONF, &sd_size); + if (sd && sd_size > 0) + ff_dovi_update_cfg(&s->dovi_ctx, (AVDOVIDecoderConfigurationRecord *) sd); + s->ref = NULL; ret = decode_nal_units(s, avpkt->data, avpkt->size); if (ret < 0) @@ -3512,6 +3577,9 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) pic_arrays_free(s); + ff_dovi_ctx_unref(&s->dovi_ctx); + av_buffer_unref(&s->rpu_buf); + av_freep(&s->md5_ctx); av_freep(&s->cabac_state); @@ -3594,6 +3662,7 @@ static av_cold int hevc_init_context(AVCodecContext *avctx) ff_bswapdsp_init(&s->bdsp); + s->dovi_ctx.logctx = avctx; s->context_initialized = 1; s->eos = 0; @@ -3698,6 +3767,14 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (ret < 0) return ret; + ret = av_buffer_replace(&s->rpu_buf, s0->rpu_buf); + if (ret < 0) + return ret; + + ret = ff_dovi_ctx_replace(&s->dovi_ctx, &s0->dovi_ctx); + 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; @@ -3754,6 +3831,8 @@ static void hevc_decode_flush(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; ff_hevc_flush_dpb(s); ff_hevc_reset_sei(&s->sei); + ff_dovi_ctx_flush(&s->dovi_ctx); + av_buffer_unref(&s->rpu_buf); s->max_ra = INT_MAX; s->eos = 1; } diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index 77fdf90da1..157bc6926f 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -32,6 +32,7 @@ #include "avcodec.h" #include "bswapdsp.h" #include "cabac.h" +#include "dovi_rpu.h" #include "get_bits.h" #include "hevcpred.h" #include "h2645_parse.h" @@ -572,6 +573,9 @@ typedef struct HEVCContext { int nal_length_size; ///< Number of bytes used for nal length (1, 2 or 4) int nuh_layer_id; + + AVBufferRef *rpu_buf; ///< 0 or 1 Dolby Vision RPUs. + DOVIContext dovi_ctx; ///< Dolby Vision decoding context } HEVCContext; /** diff --git a/libavcodec/hpeldsp.c b/libavcodec/hpeldsp.c index 8e2fd8fcf5..843ba399c5 100644 --- a/libavcodec/hpeldsp.c +++ b/libavcodec/hpeldsp.c @@ -367,4 +367,6 @@ av_cold void ff_hpeldsp_init(HpelDSPContext *c, int flags) ff_hpeldsp_init_x86(c, flags); if (ARCH_MIPS) ff_hpeldsp_init_mips(c, flags); + if (ARCH_LOONGARCH64) + ff_hpeldsp_init_loongarch(c, flags); } diff --git a/libavcodec/hpeldsp.h b/libavcodec/hpeldsp.h index 768139bfc9..45e81b10a5 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/hwaccels.h b/libavcodec/hwaccels.h index 8e54cf73f9..1e7b464950 100644 --- a/libavcodec/hwaccels.h +++ b/libavcodec/hwaccels.h @@ -60,6 +60,7 @@ extern const AVHWAccel ff_mpeg4_nvdec_hwaccel; extern const AVHWAccel ff_mpeg4_vaapi_hwaccel; extern const AVHWAccel ff_mpeg4_vdpau_hwaccel; extern const AVHWAccel ff_mpeg4_videotoolbox_hwaccel; +extern const AVHWAccel ff_prores_videotoolbox_hwaccel; extern const AVHWAccel ff_vc1_d3d11va_hwaccel; extern const AVHWAccel ff_vc1_d3d11va2_hwaccel; extern const AVHWAccel ff_vc1_dxva2_hwaccel; @@ -74,6 +75,7 @@ extern const AVHWAccel ff_vp9_dxva2_hwaccel; extern const AVHWAccel ff_vp9_nvdec_hwaccel; extern const AVHWAccel ff_vp9_vaapi_hwaccel; extern const AVHWAccel ff_vp9_vdpau_hwaccel; +extern const AVHWAccel ff_vp9_videotoolbox_hwaccel; extern const AVHWAccel ff_wmv3_d3d11va_hwaccel; extern const AVHWAccel ff_wmv3_d3d11va2_hwaccel; extern const AVHWAccel ff_wmv3_dxva2_hwaccel; diff --git a/libavcodec/idctdsp.c b/libavcodec/idctdsp.c index 846ed0b0f8..71bd03c606 100644 --- a/libavcodec/idctdsp.c +++ b/libavcodec/idctdsp.c @@ -315,6 +315,8 @@ av_cold void ff_idctdsp_init(IDCTDSPContext *c, AVCodecContext *avctx) ff_idctdsp_init_x86(c, avctx, high_bit_depth); if (ARCH_MIPS) ff_idctdsp_init_mips(c, avctx, high_bit_depth); + if (ARCH_LOONGARCH) + ff_idctdsp_init_loongarch(c, avctx, high_bit_depth); ff_init_scantable_permutation(c->idct_permutation, c->perm_type); diff --git a/libavcodec/idctdsp.h b/libavcodec/idctdsp.h index ca21a31a02..014488aec3 100644 --- a/libavcodec/idctdsp.h +++ b/libavcodec/idctdsp.h @@ -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 6a4c466b44..1dcf0e00ed 100644 --- a/libavcodec/iff.c +++ b/libavcodec/iff.c @@ -1456,6 +1456,7 @@ static void decode_delta_l(uint8_t *dst, int planepitch_byte = (w + 7) / 8; int planepitch = ((w + 15) / 16) * 2; int pitch = planepitch * bpp; + int count = 0; if (buf_end - buf <= 64) return; @@ -1487,6 +1488,8 @@ static void decode_delta_l(uint8_t *dst, int16_t cnt = bytestream2_get_be16(&ogb); uint16_t data; + if (count > dst_size) + break; offset = ((2 * offset) / planepitch_byte) * pitch + ((2 * offset) % planepitch_byte) + k * planepitch; if (cnt < 0) { if (bytestream2_get_bytes_left(&dgb) < 2) @@ -1494,6 +1497,7 @@ static void decode_delta_l(uint8_t *dst, bytestream2_seek_p(&pb, offset, SEEK_SET); cnt = -cnt; data = bytestream2_get_be16(&dgb); + count += cnt; for (i = 0; i < cnt; i++) { bytestream2_put_be16(&pb, data); bytestream2_skip_p(&pb, dstpitch - 2); @@ -1502,6 +1506,7 @@ static void decode_delta_l(uint8_t *dst, if (bytestream2_get_bytes_left(&dgb) < 2*cnt) break; bytestream2_seek_p(&pb, offset, SEEK_SET); + count += cnt; for (i = 0; i < cnt; i++) { data = bytestream2_get_be16(&dgb); bytestream2_put_be16(&pb, data); diff --git a/libavcodec/imc.c b/libavcodec/imc.c index cbe3edeeec..116c273ba0 100644 --- a/libavcodec/imc.c +++ b/libavcodec/imc.c @@ -829,7 +829,7 @@ static void imc_get_coeffs(AVCodecContext *avctx, static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) { int i, j; - int bits, summer; + int summer; for (i = 0; i < BANDS; i++) { chctx->sumLenArr[i] = 0; @@ -853,7 +853,7 @@ static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) } /* calculate bits left, bits needed and adjust bit allocation */ - bits = summer = 0; + summer = 0; for (i = 0; i < BANDS; i++) { if (chctx->bandFlagsBuf[i]) { @@ -863,7 +863,6 @@ static void imc_refine_bit_allocation(IMCContext *q, IMCChannel *chctx) chctx->CWlengthT[j] = 0; } } - bits += chctx->skipFlagBits[i]; summer -= chctx->skipFlagBits[i]; } } diff --git a/libavcodec/intelh263dec.c b/libavcodec/intelh263dec.c index 7c794dc5e3..58c1b63c0a 100644 --- a/libavcodec/intelh263dec.c +++ b/libavcodec/intelh263dec.c @@ -66,7 +66,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) { diff --git a/libavcodec/internal.h b/libavcodec/internal.h index b6180f15a5..72ca1553f6 100644 --- a/libavcodec/internal.h +++ b/libavcodec/internal.h @@ -112,10 +112,6 @@ # define STRIDE_ALIGN 8 #endif -typedef struct DecodeSimpleContext { - AVPacket *in_pkt; -} DecodeSimpleContext; - typedef struct EncodeSimpleContext { AVFrame *in_frame; } EncodeSimpleContext; @@ -137,7 +133,15 @@ typedef struct AVCodecInternal { void *thread_ctx; - DecodeSimpleContext ds; + /** + * This packet is used to hold the packet given to decoders + * implementing the .decode API; it is unused by the generic + * code for decoders implementing the .receive_frame API and + * may be freely used (but not freed) by them with the caveat + * that the packet will be unreferenced generically in + * avcodec_flush_buffers(). + */ + AVPacket *in_pkt; AVBSFContext *bsf; /** @@ -221,7 +225,7 @@ extern const uint8_t ff_log2_run[41]; */ int ff_match_2uint16(const uint16_t (*tab)[2], int size, int a, int b); -unsigned int avpriv_toupper4(unsigned int x); +unsigned int ff_toupper4(unsigned int x); void ff_color_frame(AVFrame *frame, const int color[4]); @@ -359,10 +363,4 @@ int ff_int_from_list_or_default(void *ctx, const char * val_name, int val, void ff_dvdsub_parse_palette(uint32_t *palette, const char *p); -#if defined(_WIN32) && CONFIG_SHARED && !defined(BUILDING_avcodec) -# define av_export_avcodec __declspec(dllimport) -#else -# define av_export_avcodec -#endif - #endif /* AVCODEC_INTERNAL_H */ diff --git a/libavcodec/ituh263dec.c b/libavcodec/ituh263dec.c index 3f982f414f..5329e62a5e 100644 --- a/libavcodec/ituh263dec.c +++ b/libavcodec/ituh263dec.c @@ -439,6 +439,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 +666,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 +1150,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 +1179,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; diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c index 79c8c9999e..5a7791111e 100644 --- a/libavcodec/ituh263enc.c +++ b/libavcodec/ituh263enc.c @@ -39,7 +39,6 @@ #include "mathops.h" #include "mpegutils.h" #include "flv.h" -#include "mpeg4video.h" #include "internal.h" /** @@ -445,6 +444,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 +592,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) diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c index fa6fc208f5..c06752f43a 100644 --- a/libavcodec/j2kenc.c +++ b/libavcodec/j2kenc.c @@ -1272,7 +1272,6 @@ static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) double min = DBL_MAX; double max = 0; double thresh; - int tile_disto = 0; Jpeg2000CodingStyle *codsty = &s->codsty; @@ -1294,7 +1293,6 @@ static void makelayers(Jpeg2000EncoderContext *s, Jpeg2000Tile *tile) int dr; double dd, drslope; - tile_disto += pass->disto; if (passno == 0) { dr = (int32_t)pass->rate; dd = pass->disto; diff --git a/libavcodec/jpeglsdec.c b/libavcodec/jpeglsdec.c index 32c0d2eb3f..269c71dc18 100644 --- a/libavcodec/jpeglsdec.c +++ b/libavcodec/jpeglsdec.c @@ -277,7 +277,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; } diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c index beae3bb77f..83b2350a15 100644 --- a/libavcodec/jpeglsenc.c +++ b/libavcodec/jpeglsenc.c @@ -32,7 +32,7 @@ #include "encode.h" #include "get_bits.h" #include "put_bits.h" -#include "golomb.h" +#include "put_golomb.h" #include "internal.h" #include "mathops.h" #include "mjpeg.h" diff --git a/libavcodec/jpegtables.c b/libavcodec/jpegtables.c index ef3f8dee20..e453fcf90d 100644 --- a/libavcodec/jpegtables.c +++ b/libavcodec/jpegtables.c @@ -30,8 +30,7 @@ * MJPEG encoder and decoder. */ -#include "jpegtables.h" - +#include "jpegtabs.h" #if 0 /* These are the sample quantization tables given in JPEG spec section K.1. @@ -59,66 +58,3 @@ static const unsigned char std_chrominance_quant_tbl[64] = { 99, 99, 99, 99, 99, 99, 99, 99 }; #endif - -/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ -/* IMPORTANT: these are only valid for 8-bit data precision! */ -const uint8_t avpriv_mjpeg_bits_dc_luminance[17] = -{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; -const uint8_t avpriv_mjpeg_val_dc[12] = -{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; - -const uint8_t avpriv_mjpeg_bits_dc_chrominance[17] = -{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; - -const uint8_t avpriv_mjpeg_bits_ac_luminance[17] = -{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; -const uint8_t avpriv_mjpeg_val_ac_luminance[] = -{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, - 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, - 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, - 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, - 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, - 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, - 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, - 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, - 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, - 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, - 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, - 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, - 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; - -const uint8_t avpriv_mjpeg_bits_ac_chrominance[17] = -{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; - -const uint8_t avpriv_mjpeg_val_ac_chrominance[] = -{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, - 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, - 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, - 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, - 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, - 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, - 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, - 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, - 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, - 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, - 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, - 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, - 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, - 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, - 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, - 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, - 0xf9, 0xfa -}; diff --git a/libavcodec/jpegtables.h b/libavcodec/jpegtables.h index 0907280445..49b5ecdeb0 100644 --- a/libavcodec/jpegtables.h +++ b/libavcodec/jpegtables.h @@ -23,17 +23,15 @@ #include -#include "internal.h" +extern const uint8_t ff_mjpeg_bits_dc_luminance[]; +extern const uint8_t ff_mjpeg_val_dc[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_dc[]; +extern const uint8_t ff_mjpeg_bits_dc_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_dc_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_luminance[]; +extern const uint8_t ff_mjpeg_val_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_luminance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_luminance[]; - -extern av_export_avcodec const uint8_t avpriv_mjpeg_bits_ac_chrominance[]; -extern av_export_avcodec const uint8_t avpriv_mjpeg_val_ac_chrominance[]; +extern const uint8_t ff_mjpeg_bits_ac_chrominance[]; +extern const uint8_t ff_mjpeg_val_ac_chrominance[]; #endif /* AVCODEC_JPEGTABLES_H */ diff --git a/libavcodec/jpegtabs.h b/libavcodec/jpegtabs.h new file mode 100644 index 0000000000..7106f66df0 --- /dev/null +++ b/libavcodec/jpegtabs.h @@ -0,0 +1,92 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-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 + */ + +#ifndef AVCODEC_JPEGTABS_H +#define AVCODEC_JPEGTABS_H + +#include +#include "jpegtables.h" + +/* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ +/* IMPORTANT: these are only valid for 8-bit data precision! */ +const uint8_t ff_mjpeg_bits_dc_luminance[17] = +{ /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +const uint8_t ff_mjpeg_val_dc[12] = +{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; + +const uint8_t ff_mjpeg_bits_dc_chrominance[17] = +{ /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; + +const uint8_t ff_mjpeg_bits_ac_luminance[17] = +{ /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; +const uint8_t ff_mjpeg_val_ac_luminance[] = +{ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +const uint8_t ff_mjpeg_bits_ac_chrominance[17] = +{ /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; + +const uint8_t ff_mjpeg_val_ac_chrominance[] = +{ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; +#endif diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c index 75ecc08970..64a627ed1c 100644 --- a/libavcodec/libaomdec.c +++ b/libavcodec/libaomdec.c @@ -224,9 +224,13 @@ static int aom_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((img->fmt & AOM_IMG_FMT_HIGHBITDEPTH) && img->bit_depth == 8) image_copy_16_to_8(picture, img); - else - av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes, - img->stride, avctx->pix_fmt, img->d_w, img->d_h); + else { + const uint8_t *planes[4] = { img->planes[0], img->planes[1], img->planes[2] }; + const int stride[4] = { img->stride[0], img->stride[1], img->stride[2] }; + + av_image_copy(picture->data, picture->linesize, planes, + stride, avctx->pix_fmt, img->d_w, img->d_h); + } *got_frame = 1; } return avpkt->size; @@ -241,7 +245,7 @@ static av_cold int aom_free(AVCodecContext *avctx) static av_cold int av1_init(AVCodecContext *avctx) { - return aom_init(avctx, &aom_codec_av1_dx_algo); + return aom_init(avctx, aom_codec_av1_dx()); } const AVCodec ff_libaom_av1_decoder = { diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c index 800fda0591..963cc1bcbc 100644 --- a/libavcodec/libaomenc.c +++ b/libavcodec/libaomenc.c @@ -948,7 +948,6 @@ static inline void cx_pktcpy(AOMContext *ctx, dst->sz = src->data.frame.sz; dst->buf = src->data.frame.buf; #ifdef AOM_FRAME_IS_INTRAONLY - dst->have_sse = 0; dst->frame_number = ++ctx->frame_number; dst->have_sse = ctx->have_sse; if (ctx->have_sse) { diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 2807210e50..29fa4f9c3d 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -40,6 +40,9 @@ typedef struct Libdav1dContext { AVClass *class; Dav1dContext *c; + /* This packet coincides with AVCodecInternal.in_pkt + * and is not owned by us. */ + AVPacket *pkt; AVBufferPool *pool; int pool_size; @@ -214,6 +217,8 @@ static av_cold int libdav1d_init(AVCodecContext *c) #endif int res; + dav1d->pkt = c->internal->in_pkt; + av_log(c, AV_LOG_INFO, "libdav1d %s\n", dav1d_version()); dav1d_default_settings(&s); @@ -225,12 +230,15 @@ static av_cold int libdav1d_init(AVCodecContext *c) s.frame_size_limit = c->max_pixels; if (dav1d->apply_grain >= 0) s.apply_grain = dav1d->apply_grain; - else if (c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN) - s.apply_grain = 0; + else + s.apply_grain = !(c->export_side_data & AV_CODEC_EXPORT_DATA_FILM_GRAIN); s.all_layers = dav1d->all_layers; if (dav1d->operating_point >= 0) s.operating_point = dav1d->operating_point; +#if FF_DAV1D_VERSION_AT_LEAST(6,2) + s.strict_std_compliance = c->strict_std_compliance > 0; +#endif #if FF_DAV1D_VERSION_AT_LEAST(6,0) if (dav1d->frame_threads || dav1d->tile_threads) @@ -292,34 +300,35 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) int res; if (!data->sz) { - AVPacket pkt = { 0 }; + AVPacket *const pkt = dav1d->pkt; - res = ff_decode_get_packet(c, &pkt); + res = ff_decode_get_packet(c, pkt); if (res < 0 && res != AVERROR_EOF) return res; - if (pkt.size) { - res = dav1d_data_wrap(data, pkt.data, pkt.size, libdav1d_data_free, pkt.buf); + if (pkt->size) { + res = dav1d_data_wrap(data, pkt->data, pkt->size, + libdav1d_data_free, pkt->buf); if (res < 0) { - av_packet_unref(&pkt); + av_packet_unref(pkt); return res; } - data->m.timestamp = pkt.pts; - data->m.offset = pkt.pos; - data->m.duration = pkt.duration; + data->m.timestamp = pkt->pts; + data->m.offset = pkt->pos; + data->m.duration = pkt->duration; - pkt.buf = NULL; - av_packet_unref(&pkt); + pkt->buf = NULL; + av_packet_unref(pkt); if (c->reordered_opaque != AV_NOPTS_VALUE) { - uint8_t *reordered_opaque = av_malloc(sizeof(c->reordered_opaque)); + uint8_t *reordered_opaque = av_memdup(&c->reordered_opaque, + sizeof(c->reordered_opaque)); if (!reordered_opaque) { dav1d_data_unref(data); return AVERROR(ENOMEM); } - memcpy(reordered_opaque, &c->reordered_opaque, sizeof(c->reordered_opaque)); res = dav1d_data_wrap_user_data(data, reordered_opaque, libdav1d_user_data_free, reordered_opaque); if (res < 0) { @@ -328,6 +337,9 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) return res; } } + } else if (res >= 0) { + av_packet_unref(pkt); + return AVERROR(EAGAIN); } } diff --git a/libavcodec/libkvazaar.c b/libavcodec/libkvazaar.c index aabe446a28..5f9ab43093 100644 --- a/libavcodec/libkvazaar.c +++ b/libavcodec/libkvazaar.c @@ -208,13 +208,19 @@ static int libkvazaar_encode(AVCodecContext *avctx, // Copy pixels from frame to input_pic. { + uint8_t *dst[4] = { + input_pic->data[0], + input_pic->data[1], + input_pic->data[2], + NULL, + }; int dst_linesizes[4] = { frame->width, frame->width / 2, frame->width / 2, 0 }; - av_image_copy(input_pic->data, dst_linesizes, + av_image_copy(dst, dst_linesizes, (const uint8_t **)frame->data, frame->linesize, frame->format, frame->width, frame->height); } diff --git a/libavcodec/libopenh264dec.c b/libavcodec/libopenh264dec.c index ea70a8e143..7f5e85402a 100644 --- a/libavcodec/libopenh264dec.c +++ b/libavcodec/libopenh264dec.c @@ -91,8 +91,8 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data, { SVCContext *s = avctx->priv_data; SBufferInfo info = { 0 }; - uint8_t* ptrs[3]; - int ret, linesize[3]; + uint8_t *ptrs[4] = { NULL }; + int ret, linesize[4]; AVFrame *avframe = data; DECODING_STATE state; #if OPENH264_VER_AT_LEAST(1, 7) @@ -140,6 +140,7 @@ static int svc_decode_frame(AVCodecContext *avctx, void *data, linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; + linesize[3] = 0; av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); avframe->pts = info.uiOutYuvTimeStamp; diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c index de4b85c411..7c0501a2eb 100644 --- a/libavcodec/libopenh264enc.c +++ b/libavcodec/libopenh264enc.c @@ -193,7 +193,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 +220,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 +250,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 +330,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; diff --git a/libavcodec/libvpxdec.c b/libavcodec/libvpxdec.c index 42d1b8ab1c..b2aa205036 100644 --- a/libavcodec/libvpxdec.c +++ b/libavcodec/libvpxdec.c @@ -242,11 +242,11 @@ static int vpx_decode(AVCodecContext *avctx, &ctx->decoder_alpha, #if CONFIG_LIBVPX_VP8_DECODER && CONFIG_LIBVPX_VP9_DECODER (avctx->codec_id == AV_CODEC_ID_VP8) ? - &vpx_codec_vp8_dx_algo : &vpx_codec_vp9_dx_algo + vpx_codec_vp8_dx() : vpx_codec_vp9_dx() #elif CONFIG_LIBVPX_VP8_DECODER - &vpx_codec_vp8_dx_algo + vpx_codec_vp8_dx() #else - &vpx_codec_vp9_dx_algo + vpx_codec_vp9_dx() #endif ); if (ret) @@ -350,7 +350,7 @@ static av_cold int vpx_free(AVCodecContext *avctx) static av_cold int vp8_init(AVCodecContext *avctx) { VPxContext *ctx = avctx->priv_data; - return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp8_dx_algo); + return vpx_init(avctx, &ctx->decoder, vpx_codec_vp8_dx()); } const AVCodec ff_libvpx_vp8_decoder = { @@ -372,7 +372,7 @@ const AVCodec ff_libvpx_vp8_decoder = { static av_cold int vp9_init(AVCodecContext *avctx) { VPxContext *ctx = avctx->priv_data; - return vpx_init(avctx, &ctx->decoder, &vpx_codec_vp9_dx_algo); + return vpx_init(avctx, &ctx->decoder, vpx_codec_vp9_dx()); } AVCodec ff_libvpx_vp9_decoder = { diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c index 13cdd6a022..c5e0231b12 100644 --- a/libavcodec/libx264.c +++ b/libavcodec/libx264.c @@ -104,6 +104,7 @@ typedef struct X264Context { int chroma_offset; int scenechange_threshold; int noise_reduction; + int udu_sei; AVDictionary *x264_params; @@ -138,13 +139,22 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, { X264Context *x4 = ctx->priv_data; uint8_t *p; - int i, size = x4->sei_size, ret; + uint64_t size = x4->sei_size; + int ret; if (!nnal) return 0; - for (i = 0; i < nnal; i++) + for (int i = 0; i < nnal; i++) { size += nals[i].i_payload; + /* ff_get_encode_buffer() accepts an int64_t and + * so we need to make sure that no overflow happens before + * that. With 32bit ints this is automatically true. */ +#if INT_MAX > INT64_MAX / INT_MAX - 1 + if ((int64_t)size < 0) + return AVERROR(ERANGE); +#endif + } if ((ret = ff_get_encode_buffer(ctx, pkt, size, 0)) < 0) return ret; @@ -152,21 +162,17 @@ static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, p = pkt->data; /* Write the SEI as part of the first frame. */ - if (x4->sei_size > 0 && nnal > 0) { - if (x4->sei_size > size) { - av_log(ctx, AV_LOG_ERROR, "Error: nal buffer is too small\n"); - return -1; - } + if (x4->sei_size > 0) { memcpy(p, x4->sei, x4->sei_size); p += x4->sei_size; + size -= x4->sei_size; x4->sei_size = 0; av_freep(&x4->sei); } - for (i = 0; i < nnal; i++){ - memcpy(p, nals[i].p_payload, nals[i].i_payload); - p += nals[i].i_payload; - } + /* x264 guarantees the payloads of the NALs + * to be sequential in memory. */ + memcpy(p, nals[0].p_payload, size); return 1; } @@ -293,6 +299,18 @@ static void reconfig_encoder(AVCodecContext *ctx, const AVFrame *frame) } } +static void free_picture(AVCodecContext *ctx) +{ + X264Context *x4 = ctx->priv_data; + x264_picture_t *pic = &x4->pic; + + for (int i = 0; i < pic->extra_sei.num_payloads; i++) + av_free(pic->extra_sei.payloads[i].payload); + av_freep(&pic->extra_sei.payloads); + av_freep(&pic->prop.quant_offsets); + pic->extra_sei.num_payloads = 0; +} + static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -319,6 +337,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, if (frame) { x264_sei_t *sei = &x4->pic.extra_sei; + unsigned int sei_data_size = 0; for (i = 0; i < x4->pic.img.i_plane; i++) { x4->pic.img.plane[i] = frame->data[i]; @@ -395,15 +414,17 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, roi = (const AVRegionOfInterest*)sd->data; roi_size = roi->self_size; if (!roi_size || sd->size % roi_size != 0) { + free_picture(ctx); av_log(ctx, AV_LOG_ERROR, "Invalid AVRegionOfInterest.self_size.\n"); return AVERROR(EINVAL); } nb_rois = sd->size / roi_size; qoffsets = av_calloc(mbx * mby, sizeof(*qoffsets)); - if (!qoffsets) + if (!qoffsets) { + free_picture(ctx); return AVERROR(ENOMEM); - + } // This list must be iterated in reverse because the first // region in the list applies when regions overlap. for (int i = nb_rois - 1; i >= 0; i--) { @@ -419,6 +440,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, if (roi->qoffset.den == 0) { av_free(qoffsets); + free_picture(ctx); av_log(ctx, AV_LOG_ERROR, "AVRegionOfInterest.qoffset.den must not be zero.\n"); return AVERROR(EINVAL); } @@ -443,29 +465,30 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, } } - for (int j = 0; j < frame->nb_side_data; j++) { - AVFrameSideData *side_data = frame->side_data[j]; - unsigned int sei_data_size = 0; - void *tmp; - x264_sei_payload_t *sei_payload; - if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) - continue; - tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload)); - if (!tmp) { - av_freep(&x4->pic.prop.quant_offsets); - return AVERROR(ENOMEM); + if (x4->udu_sei) { + for (int j = 0; j < frame->nb_side_data; j++) { + AVFrameSideData *side_data = frame->side_data[j]; + void *tmp; + x264_sei_payload_t *sei_payload; + if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) + continue; + tmp = av_fast_realloc(sei->payloads, &sei_data_size, (sei->num_payloads + 1) * sizeof(*sei_payload)); + if (!tmp) { + free_picture(ctx); + return AVERROR(ENOMEM); + } + sei->payloads = tmp; + sei->sei_free = av_free; + sei_payload = &sei->payloads[sei->num_payloads]; + sei_payload->payload = av_memdup(side_data->data, side_data->size); + if (!sei_payload->payload) { + free_picture(ctx); + return AVERROR(ENOMEM); + } + sei_payload->payload_size = side_data->size; + sei_payload->payload_type = SEI_TYPE_USER_DATA_UNREGISTERED; + sei->num_payloads++; } - sei->payloads = tmp; - sei->sei_free = av_free; - sei_payload = &sei->payloads[sei->num_payloads]; - sei_payload->payload = av_memdup(side_data->data, side_data->size); - if (!sei_payload->payload) { - av_freep(&x4->pic.prop.quant_offsets); - return AVERROR(ENOMEM); - } - sei_payload->payload_size = side_data->size; - sei_payload->payload_type = SEI_TYPE_USER_DATA_UNREGISTERED; - sei->num_payloads++; } } @@ -924,7 +947,7 @@ static av_cold int X264_init(AVCodecContext *avctx) #if X264_BUILD >= 142 /* Separate headers not supported in AVC-Intra mode */ - if (x4->params.i_avcintra_class >= 0) + if (x4->avcintra_class >= 0) x4->params.b_repeat_headers = 1; #endif @@ -1148,7 +1171,7 @@ static const AVOption options[] = { { "chromaoffset", "QP difference between chroma and luma", OFFSET(chroma_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, INT_MIN, INT_MAX, VE }, { "sc_threshold", "Scene change threshold", OFFSET(scenechange_threshold), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, { "noise_reduction", "Noise reduction", OFFSET(noise_reduction), AV_OPT_TYPE_INT, { .i64 = -1 }, INT_MIN, INT_MAX, VE }, - + { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "x264-params", "Override the x264 configuration using a :-separated list of key=value parameters", OFFSET(x264_params), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL }, }; diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c index 7dd70a3450..851f099343 100644 --- a/libavcodec/libx265.c +++ b/libavcodec/libx265.c @@ -54,6 +54,7 @@ typedef struct libx265Context { void *sei_data; int sei_data_size; + int udu_sei; /** * If the encoder does not support ROI then warn the first time we @@ -543,30 +544,32 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, memcpy(x265pic.userData, &pic->reordered_opaque, sizeof(pic->reordered_opaque)); } - for (i = 0; i < pic->nb_side_data; i++) { - AVFrameSideData *side_data = pic->side_data[i]; - void *tmp; - x265_sei_payload *sei_payload; + if (ctx->udu_sei) { + for (i = 0; i < pic->nb_side_data; i++) { + AVFrameSideData *side_data = pic->side_data[i]; + void *tmp; + x265_sei_payload *sei_payload; - if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) - continue; + if (side_data->type != AV_FRAME_DATA_SEI_UNREGISTERED) + continue; - tmp = av_fast_realloc(ctx->sei_data, - &ctx->sei_data_size, - (sei->numPayloads + 1) * sizeof(*sei_payload)); - if (!tmp) { - av_freep(&x265pic.userData); - av_freep(&x265pic.quantOffsets); - return AVERROR(ENOMEM); + tmp = av_fast_realloc(ctx->sei_data, + &ctx->sei_data_size, + (sei->numPayloads + 1) * sizeof(*sei_payload)); + if (!tmp) { + av_freep(&x265pic.userData); + av_freep(&x265pic.quantOffsets); + return AVERROR(ENOMEM); + } + ctx->sei_data = tmp; + sei->payloads = ctx->sei_data; + sei_payload = &sei->payloads[sei->numPayloads]; + sei_payload->payload = side_data->data; + sei_payload->payloadSize = side_data->size; + /* Equal to libx265 USER_DATA_UNREGISTERED */ + sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; + sei->numPayloads++; } - ctx->sei_data = tmp; - sei->payloads = ctx->sei_data; - sei_payload = &sei->payloads[sei->numPayloads]; - sei_payload->payload = side_data->data; - sei_payload->payloadSize = side_data->size; - /* Equal to libx265 USER_DATA_UNREGISTERED */ - sei_payload->payloadType = SEI_TYPE_USER_DATA_UNREGISTERED; - sei->numPayloads++; } } @@ -708,6 +711,7 @@ static const AVOption options[] = { { "preset", "set the x265 preset", OFFSET(preset), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "tune", "set the x265 tune parameter", OFFSET(tune), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, { "profile", "set the x265 profile", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, + { "udu_sei", "Use user data unregistered SEI if available", OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "x265-params", "set the x265 configuration using a :-separated list of key=value parameters", OFFSET(x265_opts), AV_OPT_TYPE_DICT, { 0 }, 0, 0, VE }, { NULL } }; diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c index 968ba1fb60..e15f448f90 100644 --- a/libavcodec/ljpegenc.c +++ b/libavcodec/ljpegenc.c @@ -238,7 +238,7 @@ static int ljpeg_encode_frame(AVCodecContext *avctx, AVPacket *pkt, init_put_bits(&pb, pkt->data, pkt->size); - ff_mjpeg_encode_picture_header(avctx, &pb, &s->scantable, + ff_mjpeg_encode_picture_header(avctx, &pb, NULL, &s->scantable, s->pred, s->matrix, s->matrix); header_bits = put_bits_count(&pb); @@ -293,12 +293,12 @@ static av_cold int ljpeg_encode_init(AVCodecContext *avctx) ff_mjpeg_build_huffman_codes(s->huff_size_dc_luminance, s->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(s->huff_size_dc_chrominance, s->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); return 0; } diff --git a/libavcodec/loongarch/Makefile b/libavcodec/loongarch/Makefile new file mode 100644 index 0000000000..3c15c2edeb --- /dev/null +++ b/libavcodec/loongarch/Makefile @@ -0,0 +1,26 @@ +OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_init_loongarch.o +OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_init_loongarch.o +OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_init_loongarch.o +OBJS-$(CONFIG_H264PRED) += loongarch/h264_intrapred_init_loongarch.o +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 +LASX-OBJS-$(CONFIG_H264CHROMA) += loongarch/h264chroma_lasx.o +LASX-OBJS-$(CONFIG_H264QPEL) += loongarch/h264qpel_lasx.o +LASX-OBJS-$(CONFIG_H264DSP) += loongarch/h264dsp_lasx.o \ + loongarch/h264idct_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 diff --git a/libavcodec/loongarch/cabac.h b/libavcodec/loongarch/cabac.h new file mode 100644 index 0000000000..e1c946fe16 --- /dev/null +++ b/libavcodec/loongarch/cabac.h @@ -0,0 +1,238 @@ +/* + * Loongson optimized cabac + * + * Copyright (c) 2020 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * Gu Xiwei(guxiwei-hf@loongson.cn) + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_CABAC_H +#define AVCODEC_LOONGARCH_CABAC_H + +#include "libavcodec/cabac.h" +#include "config.h" + +#define GET_CABAC_LOONGARCH_UNCBSR \ + "ld.bu %[bit], %[state], 0x0 \n\t" \ + "andi %[tmp0], %[c_range], 0xC0 \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "add.d %[tmp0], %[tmp0], %[tables] \n\t" \ + "add.d %[tmp0], %[tmp0], %[bit] \n\t" \ + /* tmp1: RangeLPS */ \ + "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \ + \ + "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[c_range], 0x11 \n\t" \ + "bge %[tmp0], %[c_low], 1f \n\t" \ + "move %[c_range], %[tmp1] \n\t" \ + "nor %[bit], %[bit], %[bit] \n\t" \ + "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "1: \n\t" \ + /* tmp1: *state */ \ + "add.d %[tmp0], %[tables], %[bit] \n\t" \ + "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \ + /* tmp2: lps_mask */ \ + "add.d %[tmp0], %[tables], %[c_range] \n\t" \ + "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \ + \ + "andi %[bit], %[bit], 0x01 \n\t" \ + "st.b %[tmp1], %[state], 0x0 \n\t" \ + "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \ + "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \ + \ + "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \ + "bnez %[tmp1], 1f \n\t" \ + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \ + "ctz.d %[tmp0], %[c_low] \n\t" \ + "addi.d %[tmp2], %[tmp0], -16 \n\t" \ + "revb.2h %[tmp0], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \ + "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \ + "add.d %[c_low], %[c_low], %[tmp0] \n\t" \ + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" \ + "1: \n\t" \ + +#define GET_CABAC_LOONGARCH \ + "ld.bu %[bit], %[state], 0x0 \n\t" \ + "andi %[tmp0], %[c_range], 0xC0 \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "add.d %[tmp0], %[tmp0], %[tables] \n\t" \ + "add.d %[tmp0], %[tmp0], %[bit] \n\t" \ + /* tmp1: RangeLPS */ \ + "ld.bu %[tmp1], %[tmp0], %[lps_off] \n\t" \ + \ + "sub.d %[c_range], %[c_range], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[c_range], 0x11 \n\t" \ + "bge %[tmp0], %[c_low], 1f \n\t" \ + "move %[c_range], %[tmp1] \n\t" \ + "nor %[bit], %[bit], %[bit] \n\t" \ + "sub.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "1: \n\t" \ + /* tmp1: *state */ \ + "add.d %[tmp0], %[tables], %[bit] \n\t" \ + "ld.bu %[tmp1], %[tmp0], %[mlps_off] \n\t" \ + /* tmp2: lps_mask */ \ + "add.d %[tmp0], %[tables], %[c_range] \n\t" \ + "ld.bu %[tmp2], %[tmp0], %[norm_off] \n\t" \ + \ + "andi %[bit], %[bit], 0x01 \n\t" \ + "st.b %[tmp1], %[state], 0x0 \n\t" \ + "sll.d %[c_range], %[c_range], %[tmp2] \n\t" \ + "sll.d %[c_low], %[c_low], %[tmp2] \n\t" \ + \ + "and %[tmp1], %[c_low], %[cabac_mask] \n\t" \ + "bnez %[tmp1], 1f \n\t" \ + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" \ + "ctz.d %[tmp0], %[c_low] \n\t" \ + "addi.d %[tmp2], %[tmp0], -16 \n\t" \ + "revb.2h %[tmp0], %[tmp1] \n\t" \ + "slli.d %[tmp0], %[tmp0], 0x01 \n\t" \ + "sub.d %[tmp0], %[tmp0], %[cabac_mask] \n\t" \ + "sll.d %[tmp0], %[tmp0], %[tmp2] \n\t" \ + \ + "add.d %[c_low], %[c_low], %[tmp0] \n\t" \ + \ + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" \ + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \ + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" \ + "1: \n\t" \ + +#define get_cabac_inline get_cabac_inline_loongarch +static av_always_inline +int get_cabac_inline_loongarch(CABACContext *c, uint8_t * const state) +{ + int64_t tmp0, tmp1, tmp2, bit; + + __asm__ volatile ( +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream) + : [state]"r"(state), [tables]"r"(ff_h264_cabac_tables), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK) + : "memory" + ); + + return bit; +} + +#define get_cabac_bypass get_cabac_bypass_loongarch +static av_always_inline int get_cabac_bypass_loongarch(CABACContext *c) +{ + int64_t tmp0, tmp1, tmp2; + int res = 0; + __asm__ volatile( + "slli.d %[c_low], %[c_low], 0x01 \n\t" + "and %[tmp0], %[c_low], %[cabac_mask] \n\t" + "bnez %[tmp0], 1f \n\t" + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" +#if UNCHECKED_BITSTREAM_READER + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" +#else + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" +#endif + "revb.2h %[tmp1], %[tmp1] \n\t" + "slli.d %[tmp1], %[tmp1], 0x01 \n\t" + "sub.d %[tmp1], %[tmp1], %[cabac_mask] \n\t" + "add.d %[c_low], %[c_low], %[tmp1] \n\t" + "1: \n\t" + "slli.d %[tmp1], %[c_range], 0x11 \n\t" + "slt %[tmp0], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[c_low], %[tmp1] \n\t" + "masknez %[tmp2], %[one], %[tmp0] \n\t" + "maskeqz %[res], %[res], %[tmp0] \n\t" + "or %[res], %[res], %[tmp2] \n\t" + "masknez %[tmp2], %[tmp1], %[tmp0] \n\t" + "maskeqz %[c_low], %[c_low], %[tmp0] \n\t" + "or %[c_low], %[c_low], %[tmp2] \n\t" + : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream), [res]"+&r"(res) + : [cabac_mask]"r"(CABAC_MASK), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [one]"r"(0x01) + : "memory" + ); + return res; +} + +#define get_cabac_bypass_sign get_cabac_bypass_sign_loongarch +static av_always_inline +int get_cabac_bypass_sign_loongarch(CABACContext *c, int val) +{ + int64_t tmp0, tmp1; + int res = val; + __asm__ volatile( + "slli.d %[c_low], %[c_low], 0x01 \n\t" + "and %[tmp0], %[c_low], %[cabac_mask] \n\t" + "bnez %[tmp0], 1f \n\t" + "ld.hu %[tmp1], %[c_bytestream], 0x0 \n\t" +#if UNCHECKED_BITSTREAM_READER + "addi.d %[c_bytestream], %[c_bytestream], 0x02 \n\t" +#else + "slt %[tmp0], %[c_bytestream], %[c_bytestream_end] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" + "add.d %[c_bytestream], %[c_bytestream], %[tmp0] \n\t" +#endif + "revb.2h %[tmp1], %[tmp1] \n\t" + "slli.d %[tmp1], %[tmp1], 0x01 \n\t" + "sub.d %[tmp1], %[tmp1], %[cabac_mask] \n\t" + "add.d %[c_low], %[c_low], %[tmp1] \n\t" + "1: \n\t" + "slli.d %[tmp1], %[c_range], 0x11 \n\t" + "slt %[tmp0], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[c_low], %[tmp1] \n\t" + "masknez %[tmp1], %[tmp1], %[tmp0] \n\t" + "maskeqz %[c_low], %[c_low], %[tmp0] \n\t" + "or %[c_low], %[c_low], %[tmp1] \n\t" + "sub.d %[tmp1], %[zero], %[res] \n\t" + "maskeqz %[tmp1], %[tmp1], %[tmp0] \n\t" + "masknez %[res], %[res], %[tmp0] \n\t" + "or %[res], %[res], %[tmp1] \n\t" + : [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [res]"+&r"(res), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), + [c_bytestream]"+&r"(c->bytestream) + : [cabac_mask]"r"(CABAC_MASK), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [zero]"r"(0x0) + : "memory" + ); + + return res; +} +#endif /* AVCODEC_LOONGARCH_CABAC_H */ diff --git a/libavcodec/loongarch/h264_cabac.c b/libavcodec/loongarch/h264_cabac.c new file mode 100644 index 0000000000..d88743bed7 --- /dev/null +++ b/libavcodec/loongarch/h264_cabac.c @@ -0,0 +1,140 @@ +/* + * Loongson optimized cabac + * + * 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 "libavcodec/cabac.h" +#include "cabac.h" + +#define decode_significance decode_significance_loongarch +static int decode_significance_loongarch(CABACContext *c, int max_coeff, + uint8_t *significant_coeff_ctx_base, int *index, int64_t last_off) +{ + void *end = significant_coeff_ctx_base + max_coeff - 1; + int64_t minusstart = -(int64_t)significant_coeff_ctx_base; + int64_t minusindex = 4 - (int64_t)index; + int64_t bit, tmp0, tmp1, tmp2, one = 1; + uint8_t *state = significant_coeff_ctx_base; + + __asm__ volatile( + "3:" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "blt %[bit], %[one], 4f \n\t" + "add.d %[state], %[state], %[last_off] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "sub.d %[state], %[state], %[last_off] \n\t" + "add.d %[tmp0], %[state], %[minusstart] \n\t" + "st.w %[tmp0], %[index], 0 \n\t" + "bge %[bit], %[one], 5f \n\t" + "addi.d %[index], %[index], 4 \n\t" + "4: \n\t" + "addi.d %[state], %[state], 1 \n\t" + "blt %[state], %[end], 3b \n\t" + "add.d %[tmp0], %[state], %[minusstart] \n\t" + "st.w %[tmp0], %[index], 0 \n\t" + "5: \n\t" + "add.d %[tmp0], %[index], %[minusindex] \n\t" + "srli.d %[tmp0], %[tmp0], 2 \n\t" + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), [tmp2]"=&r"(tmp2), + [c_range]"+&r"(c->range), [c_low]"+&r"(c->low), [state]"+&r"(state), + [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index) + : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), [one]"r"(one), + [minusstart]"r"(minusstart), [minusindex]"r"(minusindex), + [last_off]"r"(last_off), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK) + : "memory" + ); + + return (int)tmp0; +} + +#define decode_significance_8x8 decode_significance_8x8_loongarch +static int decode_significance_8x8_loongarch( + CABACContext *c, uint8_t *significant_coeff_ctx_base, + int *index, uint8_t *last_coeff_ctx_base, const uint8_t *sig_off) +{ + int64_t minusindex = 4 - (int64_t)index; + int64_t bit, tmp0, tmp1, tmp2, one = 1, end = 63, last = 0; + uint8_t *state = 0; + int64_t flag_offset = H264_LAST_COEFF_FLAG_OFFSET_8x8_OFFSET; + + __asm__ volatile( + "3: \n\t" + "ldx.bu %[tmp0], %[sig_off], %[last] \n\t" + "add.d %[state], %[tmp0], %[significant_coeff_ctx_base] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "blt %[bit], %[one], 4f \n\t" + "add.d %[tmp0], %[tables], %[flag_offset] \n\t" + "ldx.bu %[tmp1], %[tmp0], %[last] \n\t" + "add.d %[state], %[tmp1], %[last_coeff_ctx_base] \n\t" +#if UNCHECKED_BITSTREAM_READER + GET_CABAC_LOONGARCH_UNCBSR +#else + GET_CABAC_LOONGARCH +#endif + "st.w %[last], %[index], 0 \n\t" + "bge %[bit], %[one], 5f \n\t" + "addi.d %[index], %[index], 4 \n\t" + "4: \n\t" + "addi.d %[last], %[last], 1 \n\t" + "blt %[last], %[end], 3b \n\t" + "st.w %[last], %[index], 0 \n\t" + "5: \n\t" + "add.d %[tmp0], %[index], %[minusindex] \n\t" + "srli.d %[tmp0], %[tmp0], 2 \n\t" + : [bit]"=&r"(bit), [tmp0]"=&r"(tmp0), [tmp1]"=&r"(tmp1), + [tmp2]"=&r"(tmp2), [c_range]"+&r"(c->range), + [c_low]"+&r"(c->low), [state]"+&r"(state), [last]"+&r"(last), + [c_bytestream]"+&r"(c->bytestream), [index]"+&r"(index) + : [tables]"r"(ff_h264_cabac_tables), [end]"r"(end), + [one]"r"(one), [minusindex]"r"(minusindex), + [last_coeff_ctx_base]"r"(last_coeff_ctx_base), + [flag_offset]"r"(flag_offset), +#if !UNCHECKED_BITSTREAM_READER + [c_bytestream_end]"r"(c->bytestream_end), +#endif + [lps_off]"i"(H264_LPS_RANGE_OFFSET), [sig_off]"r"(sig_off), + [mlps_off]"i"(H264_MLPS_STATE_OFFSET + 128), + [norm_off]"i"(H264_NORM_SHIFT_OFFSET), + [cabac_mask]"r"(CABAC_MASK), + [significant_coeff_ctx_base]"r"(significant_coeff_ctx_base) + ); + + return (int)tmp0; +} diff --git a/libavcodec/loongarch/h264_deblock_lasx.c b/libavcodec/loongarch/h264_deblock_lasx.c new file mode 100644 index 0000000000..c89bea9a84 --- /dev/null +++ b/libavcodec/loongarch/h264_deblock_lasx.c @@ -0,0 +1,147 @@ +/* + * 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/bit_depth_template.c" +#include "h264dsp_lasx.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +#define H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(edges, step, mask_mv, dir, \ + d_idx, mask_dir) \ +do { \ + int b_idx = 0; \ + int step_x4 = step << 2; \ + int d_idx_12 = d_idx + 12; \ + int d_idx_52 = d_idx + 52; \ + int d_idx_x4 = d_idx << 2; \ + int d_idx_x4_48 = d_idx_x4 + 48; \ + int dir_x32 = dir * 32; \ + uint8_t *ref_t = (uint8_t*)ref; \ + uint8_t *mv_t = (uint8_t*)mv; \ + uint8_t *nnz_t = (uint8_t*)nnz; \ + uint8_t *bS_t = (uint8_t*)bS; \ + mask_mv <<= 3; \ + for (; b_idx < edges; b_idx += step) { \ + out &= mask_dir; \ + if (!(mask_mv & b_idx)) { \ + if (bidir) { \ + ref2 = __lasx_xvldx(ref_t, d_idx_12); \ + ref3 = __lasx_xvldx(ref_t, d_idx_52); \ + ref0 = __lasx_xvld(ref_t, 12); \ + ref1 = __lasx_xvld(ref_t, 52); \ + ref2 = __lasx_xvilvl_w(ref3, ref2); \ + ref0 = __lasx_xvilvl_w(ref0, ref0); \ + ref1 = __lasx_xvilvl_w(ref1, ref1); \ + ref3 = __lasx_xvshuf4i_w(ref2, 0xB1); \ + ref0 = __lasx_xvsub_b(ref0, ref2); \ + ref1 = __lasx_xvsub_b(ref1, ref3); \ + ref0 = __lasx_xvor_v(ref0, ref1); \ +\ + tmp2 = __lasx_xvldx(mv_t, d_idx_x4_48); \ + tmp3 = __lasx_xvld(mv_t, 48); \ + tmp4 = __lasx_xvld(mv_t, 208); \ + tmp5 = __lasx_xvld(mv_t + d_idx_x4, 208); \ + DUP2_ARG3(__lasx_xvpermi_q, tmp2, tmp2, 0x20, tmp5, tmp5, \ + 0x20, tmp2, tmp5); \ + tmp3 = __lasx_xvpermi_q(tmp4, tmp3, 0x20); \ + tmp2 = __lasx_xvsub_h(tmp2, tmp3); \ + tmp5 = __lasx_xvsub_h(tmp5, tmp3); \ + DUP2_ARG2(__lasx_xvsat_h, tmp2, 7, tmp5, 7, tmp2, tmp5); \ + tmp0 = __lasx_xvpickev_b(tmp5, tmp2); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xd8); \ + tmp0 = __lasx_xvadd_b(tmp0, cnst_1); \ + tmp0 = __lasx_xvssub_bu(tmp0, cnst_0); \ + tmp0 = __lasx_xvsat_h(tmp0, 7); \ + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xd8); \ + tmp1 = __lasx_xvpickod_d(tmp0, tmp0); \ + out = __lasx_xvor_v(ref0, tmp0); \ + tmp1 = __lasx_xvshuf4i_w(tmp1, 0xB1); \ + out = __lasx_xvor_v(out, tmp1); \ + tmp0 = __lasx_xvshuf4i_w(out, 0xB1); \ + out = __lasx_xvmin_bu(out, tmp0); \ + } else { \ + ref0 = __lasx_xvldx(ref_t, d_idx_12); \ + ref3 = __lasx_xvld(ref_t, 12); \ + tmp2 = __lasx_xvldx(mv_t, d_idx_x4_48); \ + tmp3 = __lasx_xvld(mv_t, 48); \ + tmp4 = __lasx_xvsub_h(tmp3, tmp2); \ + tmp1 = __lasx_xvsat_h(tmp4, 7); \ + tmp1 = __lasx_xvpickev_b(tmp1, tmp1); \ + tmp1 = __lasx_xvadd_b(tmp1, cnst_1); \ + out = __lasx_xvssub_bu(tmp1, cnst_0); \ + out = __lasx_xvsat_h(out, 7); \ + out = __lasx_xvpickev_b(out, out); \ + ref0 = __lasx_xvsub_b(ref3, ref0); \ + out = __lasx_xvor_v(out, ref0); \ + } \ + } \ + tmp0 = __lasx_xvld(nnz_t, 12); \ + tmp1 = __lasx_xvldx(nnz_t, d_idx_12); \ + tmp0 = __lasx_xvor_v(tmp0, tmp1); \ + tmp0 = __lasx_xvmin_bu(tmp0, cnst_2); \ + out = __lasx_xvmin_bu(out, cnst_2); \ + tmp0 = __lasx_xvslli_h(tmp0, 1); \ + tmp0 = __lasx_xvmax_bu(out, tmp0); \ + tmp0 = __lasx_vext2xv_hu_bu(tmp0); \ + __lasx_xvstelm_d(tmp0, bS_t + dir_x32, 0, 0); \ + ref_t += step; \ + mv_t += step_x4; \ + nnz_t += step; \ + bS_t += step; \ + } \ +} while(0) + +void ff_h264_loop_filter_strength_lasx(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field) +{ + __m256i out; + __m256i ref0, ref1, ref2, ref3; + __m256i tmp0, tmp1; + __m256i tmp2, tmp3, tmp4, tmp5; + __m256i cnst_0, cnst_1, cnst_2; + __m256i zero = __lasx_xvldi(0); + __m256i one = __lasx_xvnor_v(zero, zero); + int64_t cnst3 = 0x0206020602060206, cnst4 = 0x0103010301030103; + if (field) { + cnst_0 = __lasx_xvreplgr2vr_d(cnst3); + cnst_1 = __lasx_xvreplgr2vr_d(cnst4); + cnst_2 = __lasx_xvldi(0x01); + } else { + DUP2_ARG1(__lasx_xvldi, 0x06, 0x03, cnst_0, cnst_1); + cnst_2 = __lasx_xvldi(0x01); + } + step <<= 3; + edges <<= 3; + + H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(edges, step, mask_mv1, + 1, -8, zero); + H264_LOOP_FILTER_STRENGTH_ITERATION_LASX(32, 8, mask_mv0, 0, -1, one); + + DUP2_ARG2(__lasx_xvld, (int8_t*)bS, 0, (int8_t*)bS, 16, tmp0, tmp1); + DUP2_ARG2(__lasx_xvilvh_d, tmp0, tmp0, tmp1, tmp1, tmp2, tmp3); + LASX_TRANSPOSE4x4_H(tmp0, tmp2, tmp1, tmp3, tmp2, tmp3, tmp4, tmp5); + __lasx_xvstelm_d(tmp2, (int8_t*)bS, 0, 0); + __lasx_xvstelm_d(tmp3, (int8_t*)bS + 8, 0, 0); + __lasx_xvstelm_d(tmp4, (int8_t*)bS + 16, 0, 0); + __lasx_xvstelm_d(tmp5, (int8_t*)bS + 24, 0, 0); +} diff --git a/libavcodec/loongarch/h264_intrapred_init_loongarch.c b/libavcodec/loongarch/h264_intrapred_init_loongarch.c new file mode 100644 index 0000000000..12620bd842 --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_init_loongarch.c @@ -0,0 +1,50 @@ +/* + * 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 "libavcodec/h264pred.h" +#include "h264_intrapred_lasx.h" + +av_cold void ff_h264_pred_init_loongarch(H264PredContext *h, int codec_id, + const int bit_depth, + const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (bit_depth == 8) { + if (have_lasx(cpu_flags)) { + if (chroma_format_idc <= 1) { + } + if (codec_id == AV_CODEC_ID_VP7 || codec_id == AV_CODEC_ID_VP8) { + } else { + if (chroma_format_idc <= 1) { + } + if (codec_id == AV_CODEC_ID_SVQ3) { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_svq3_8_lasx; + } else if (codec_id == AV_CODEC_ID_RV40) { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_rv40_8_lasx; + } else { + h->pred16x16[PLANE_PRED8x8] = ff_h264_pred16x16_plane_h264_8_lasx; + } + } + } + } +} diff --git a/libavcodec/loongarch/h264_intrapred_lasx.c b/libavcodec/loongarch/h264_intrapred_lasx.c new file mode 100644 index 0000000000..c38cd611b8 --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_lasx.c @@ -0,0 +1,121 @@ +/* + * 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 "h264_intrapred_lasx.h" + +#define PRED16X16_PLANE \ + ptrdiff_t stride_1, stride_2, stride_3, stride_4, stride_5, stride_6; \ + ptrdiff_t stride_8, stride_15; \ + int32_t res0, res1, res2, res3, cnt; \ + uint8_t *src0, *src1; \ + __m256i reg0, reg1, reg2, reg3, reg4; \ + __m256i tmp0, tmp1, tmp2, tmp3; \ + __m256i shuff = {0x0B040A0509060807, 0x0F000E010D020C03, 0, 0}; \ + __m256i mult = {0x0004000300020001, 0x0008000700060005, 0, 0}; \ + __m256i int_mult1 = {0x0000000100000000, 0x0000000300000002, \ + 0x0000000500000004, 0x0000000700000006}; \ + \ + stride_1 = -stride; \ + stride_2 = stride << 1; \ + stride_3 = stride_2 + stride; \ + stride_4 = stride_2 << 1; \ + stride_5 = stride_4 + stride; \ + stride_6 = stride_3 << 1; \ + stride_8 = stride_4 << 1; \ + stride_15 = (stride_8 << 1) - stride; \ + src0 = src - 1; \ + src1 = src0 + stride_8; \ + \ + reg0 = __lasx_xvldx(src0, -stride); \ + reg1 = __lasx_xvldx(src, (8 - stride)); \ + reg0 = __lasx_xvilvl_d(reg1, reg0); \ + reg0 = __lasx_xvshuf_b(reg0, reg0, shuff); \ + reg0 = __lasx_xvhsubw_hu_bu(reg0, reg0); \ + reg0 = __lasx_xvmul_h(reg0, mult); \ + res1 = (src1[0] - src0[stride_6]) + \ + 2 * (src1[stride] - src0[stride_5]) + \ + 3 * (src1[stride_2] - src0[stride_4]) + \ + 4 * (src1[stride_3] - src0[stride_3]) + \ + 5 * (src1[stride_4] - src0[stride_2]) + \ + 6 * (src1[stride_5] - src0[stride]) + \ + 7 * (src1[stride_6] - src0[0]) + \ + 8 * (src0[stride_15] - src0[stride_1]); \ + reg0 = __lasx_xvhaddw_w_h(reg0, reg0); \ + reg0 = __lasx_xvhaddw_d_w(reg0, reg0); \ + reg0 = __lasx_xvhaddw_q_d(reg0, reg0); \ + res0 = __lasx_xvpickve2gr_w(reg0, 0); \ + +#define PRED16X16_PLANE_END \ + res2 = (src0[stride_15] + src[15 - stride] + 1) << 4; \ + res3 = 7 * (res0 + res1); \ + res2 -= res3; \ + reg0 = __lasx_xvreplgr2vr_w(res0); \ + reg1 = __lasx_xvreplgr2vr_w(res1); \ + reg2 = __lasx_xvreplgr2vr_w(res2); \ + reg3 = __lasx_xvmul_w(reg0, int_mult1); \ + reg4 = __lasx_xvslli_w(reg0, 3); \ + reg4 = __lasx_xvadd_w(reg4, reg3); \ + for (cnt = 8; cnt--;) { \ + tmp0 = __lasx_xvadd_w(reg2, reg3); \ + tmp1 = __lasx_xvadd_w(reg2, reg4); \ + tmp0 = __lasx_xvssrani_hu_w(tmp1, tmp0, 5); \ + tmp0 = __lasx_xvpermi_d(tmp0, 0xD8); \ + reg2 = __lasx_xvadd_w(reg2, reg1); \ + tmp2 = __lasx_xvadd_w(reg2, reg3); \ + tmp3 = __lasx_xvadd_w(reg2, reg4); \ + tmp1 = __lasx_xvssrani_hu_w(tmp3, tmp2, 5); \ + tmp1 = __lasx_xvpermi_d(tmp1, 0xD8); \ + tmp0 = __lasx_xvssrani_bu_h(tmp1, tmp0, 0); \ + reg2 = __lasx_xvadd_w(reg2, reg1); \ + __lasx_xvstelm_d(tmp0, src, 0, 0); \ + __lasx_xvstelm_d(tmp0, src, 8, 2); \ + src += stride; \ + __lasx_xvstelm_d(tmp0, src, 0, 1); \ + __lasx_xvstelm_d(tmp0, src, 8, 3); \ + src += stride; \ + } + + +void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + res0 = (5 * res0 + 32) >> 6; + res1 = (5 * res1 + 32) >> 6; + PRED16X16_PLANE_END +} + +void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + res0 = (res0 + (res0 >> 2)) >> 4; + res1 = (res1 + (res1 >> 2)) >> 4; + PRED16X16_PLANE_END +} + +void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride) +{ + PRED16X16_PLANE + cnt = (5 * (res0/4)) / 16; + res0 = (5 * (res1/4)) / 16; + res1 = cnt; + PRED16X16_PLANE_END +} diff --git a/libavcodec/loongarch/h264_intrapred_lasx.h b/libavcodec/loongarch/h264_intrapred_lasx.h new file mode 100644 index 0000000000..0c2653300c --- /dev/null +++ b/libavcodec/loongarch/h264_intrapred_lasx.h @@ -0,0 +1,31 @@ +/* + * 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_H264_INTRAPRED_LASX_H +#define AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H + +#include "libavcodec/avcodec.h" + +void ff_h264_pred16x16_plane_h264_8_lasx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_rv40_8_lasx(uint8_t *src, ptrdiff_t stride); +void ff_h264_pred16x16_plane_svq3_8_lasx(uint8_t *src, ptrdiff_t stride); + +#endif // #ifndef AVCODEC_LOONGARCH_H264_INTRAPRED_LASX_H diff --git a/libavcodec/loongarch/h264chroma_init_loongarch.c b/libavcodec/loongarch/h264chroma_init_loongarch.c new file mode 100644 index 0000000000..0ca24ecc47 --- /dev/null +++ b/libavcodec/loongarch/h264chroma_init_loongarch.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 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 "h264chroma_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/h264chroma.h" + +av_cold void ff_h264chroma_init_loongarch(H264ChromaContext *c, int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lasx(cpu_flags)) { + if (bit_depth <= 8) { + c->put_h264_chroma_pixels_tab[0] = ff_put_h264_chroma_mc8_lasx; + c->avg_h264_chroma_pixels_tab[0] = ff_avg_h264_chroma_mc8_lasx; + c->put_h264_chroma_pixels_tab[1] = ff_put_h264_chroma_mc4_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264chroma_lasx.c b/libavcodec/loongarch/h264chroma_lasx.c new file mode 100644 index 0000000000..824a78dfc8 --- /dev/null +++ b/libavcodec/loongarch/h264chroma_lasx.c @@ -0,0 +1,1280 @@ +/* + * Loongson LASX optimized h264chroma + * + * Copyright (c) 2020 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 "h264chroma_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/avassert.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +static const uint8_t chroma_mask_arr[64] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 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, + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20 +}; + +static av_always_inline void avc_chroma_hv_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride_2x << 1; + __m256i src0, src1, src2, src3, src4, out; + __m256i res_hz0, res_hz1, res_hz2, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP2_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src1, src3); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP2_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src1, src3); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + res_hz2 = __lasx_xvdp2_h_bu(src3, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hv_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res_hz0, res_hz1, res_hz2, res_hz3, res_hz4; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src6, src5, 0x20, + src8, src7, 0x20, src1, src3, src5, src7); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP4_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src5, src5, mask, src7, + src7, mask, src1, src3, src5, src7); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src3, + coeff_hz_vec, src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + res_hz4 = __lasx_xvdp2_h_bu(src7, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_vt2 = __lasx_xvmul_h(res_hz3, coeff_vt_vec0); + res_vt3 = __lasx_xvmul_h(res_hz4, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3); + res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3); + DUP4_ARG3(__lasx_xvmadd_h, res_vt0, res_hz0, coeff_vt_vec1, res_vt1, res_hz1, coeff_vt_vec1, + res_vt2, res_hz2, coeff_vt_vec1, res_vt3, res_hz3, coeff_vt_vec1, + res_vt0, res_vt1, res_vt2, res_vt3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src1, src2); + src3 = __lasx_xvldx(src, stride_3x); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); + +} + +static av_always_inline void avc_chroma_hz_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + src += stride_4x; + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src5, src6); + src7 = __lasx_xvldx(src, stride_3x); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, 0x20, + src7, src6, 0x20, src0, src2, src4, src6); + DUP4_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src4, src4, mask, + src6, src6, mask, src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_nonmult_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + uint32_t row; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + mask = __lasx_xvld(chroma_mask_arr, 0); + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + + for (row = height >> 2; row--;) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + src += stride_4x; + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); + dst += stride_4x; + } + + if ((height & 3)) { + src0 = __lasx_xvld(src, 0); + src1 = __lasx_xvldx(src, stride); + src1 = __lasx_xvpermi_q(src1, src0, 0x20); + src0 = __lasx_xvshuf_b(src1, src1, mask); + res0 = __lasx_xvdp2_h_bu(src0, coeff_vec); + out = __lasx_xvssrarni_bu_h(res0, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + dst += stride; + __lasx_xvstelm_d(out, dst, 0, 2); + } +} + +static av_always_inline void avc_chroma_vt_8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i src0, src1, src2, src3, src4, out; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, 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_xvilvl_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, + src6, coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void copy_width8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + uint64_t tmp[8]; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride_2] \n\t" + "ldx.d %[tmp7], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride_2] \n\t" + "stx.d %[tmp7], %[dst], %[stride_3] \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"(dst), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +static av_always_inline void copy_width8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + uint64_t tmp[4]; + ptrdiff_t stride_2, stride_3; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + : [tmp0]"=&r"(tmp[0]), [tmp1]"=&r"(tmp[1]), + [tmp2]"=&r"(tmp[2]), [tmp3]"=&r"(tmp[3]), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3) + : [stride]"r"(stride), [dst]"r"(dst), [src]"r"(src) + : "memory" + ); +} + +static void avc_chroma_hv_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hv_8x4_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (8 == height) { + avc_chroma_hv_8x8_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } +} + +static void avc_chroma_hv_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + __m256i src0, src1, src2; + __m256i res_hz, res_vt; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + __m256i coeff_vt_vec = __lasx_xvpermi_q(coeff_vt_vec1, coeff_vt_vec0, 0x02); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2); + DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src0, src1); + src0 = __lasx_xvpermi_q(src0, src1, 0x02); + res_hz = __lasx_xvdp2_h_bu(src0, coeff_hz_vec); + res_vt = __lasx_xvmul_h(res_hz, coeff_vt_vec); + res_hz = __lasx_xvpermi_q(res_hz, res_vt, 0x01); + res_vt = __lasx_xvadd_h(res_hz, res_vt); + res_vt = __lasx_xvssrarni_bu_h(res_vt, res_vt, 6); + __lasx_xvstelm_w(res_vt, dst, 0, 0); + __lasx_xvstelm_w(res_vt, dst + stride, 0, 1); +} + +static void avc_chroma_hv_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4; + __m256i res_hz0, res_hz1, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask, + src4, src3, mask, src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src0, src1); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + DUP2_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_vt0, res_vt1); + res_hz0 = __lasx_xvadd_h(res_vt0, res_vt1); + res_hz0 = __lasx_xvssrarni_bu_h(res_hz0, res_hz0, 6); + __lasx_xvstelm_w(res_hz0, dst, 0, 0); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5); +} + +static void avc_chroma_hv_4x8_lasx(uint8_t *src, uint8_t * dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i res_hz0, res_hz1, res_hz2, res_hz3; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src2, src1, mask, src3, src2, mask, + src4, src3, mask, src0, src1, src2, src3); + DUP4_ARG3(__lasx_xvshuf_b, src5, src4, mask, src6, src5, mask, src7, src6, mask, + src8, src7, mask, src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src1, src3, 0x02, src4, src6, 0x02, + src5, src7, 0x02, src0, src1, src4, src5); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src4, coeff_hz_vec, + src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + DUP4_ARG2(__lasx_xvmul_h, res_hz0, coeff_vt_vec1, res_hz1, coeff_vt_vec0, res_hz2, + coeff_vt_vec1, res_hz3, coeff_vt_vec0, res_vt0, res_vt1, res_vt2, res_vt3); + DUP2_ARG2(__lasx_xvadd_h, res_vt0, res_vt1, res_vt2, res_vt3, res_vt0, res_vt2); + res_hz0 = __lasx_xvssrarni_bu_h(res_vt2, res_vt0, 6); + __lasx_xvstelm_w(res_hz0, dst, 0, 0); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 1); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res_hz0, dst, 0, 2); + __lasx_xvstelm_w(res_hz0, dst + stride, 0, 3); + __lasx_xvstelm_w(res_hz0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res_hz0, dst + stride_3, 0, 7); +} + +static void avc_chroma_hv_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coef_hor0, uint32_t coef_hor1, + uint32_t coef_ver0, uint32_t coef_ver1, + int32_t height) +{ + if (8 == height) { + avc_chroma_hv_4x8_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (4 == height) { + avc_chroma_hv_4x4_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } else if (2 == height) { + avc_chroma_hv_4x2_lasx(src, dst, stride, coef_hor0, coef_hor1, coef_ver0, + coef_ver1); + } +} + +static void avc_chroma_hz_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + __m256i src0, src1; + __m256i res, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + src1 = __lasx_xvldx(src, stride); + src0 = __lasx_xvshuf_b(src1, src0, mask); + res = __lasx_xvdp2_h_bu(src0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); +} + +static void avc_chroma_hz_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + __m256i src0, src1, src2, src3; + __m256i res, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src1, src2); + src3 = __lasx_xvldx(src, stride_3); + DUP2_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src0, src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + res = __lasx_xvdp2_h_bu(src0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); + __lasx_xvstelm_w(res, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res, dst + stride_3, 0, 5); +} + +static void avc_chroma_hz_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i res0, res1, mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 32, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride_2, src5, src6); + src7 = __lasx_xvldx(src, stride_3); + DUP4_ARG3(__lasx_xvshuf_b, src1, src0, mask, src3, src2, mask, src5, src4, mask, + src7, src6, mask, src0, src2, src4, src6); + DUP2_ARG3(__lasx_xvpermi_q, src0, src2, 0x02, src4, src6, 0x02, src0, src4); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src4, coeff_vec, res0, res1); + res0 = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_w(res0, dst, 0, 0); + __lasx_xvstelm_w(res0, dst + stride, 0, 1); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res0, dst, 0, 2); + __lasx_xvstelm_w(res0, dst + stride, 0, 3); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 7); +} + +static void avc_chroma_hz_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (8 == height) { + avc_chroma_hz_4x8_lasx(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_hz_4x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (2 == height) { + avc_chroma_hz_4x2_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_hz_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hz_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_8x8_lasx(src, dst, stride, coeff0, coeff1); + } else { + avc_chroma_hz_nonmult_lasx(src, dst, stride, coeff0, coeff1, height); + } +} + +static void avc_chroma_vt_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + __m256i src0, src1, src2; + __m256i tmp0, tmp1; + __m256i res; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + src0 = __lasx_xvld(src, 0); + DUP2_ARG2(__lasx_xvldx, src, stride, src, stride << 1, src1, src2); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, tmp0, tmp1); + tmp0 = __lasx_xvilvl_d(tmp1, tmp0); + res = __lasx_xvdp2_h_bu(tmp0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); +} + +static void avc_chroma_vt_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i res; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp2); + tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02); + res = __lasx_xvdp2_h_bu(tmp0, coeff_vec); + res = __lasx_xvslli_h(res, 3); + res = __lasx_xvssrarni_bu_h(res, res, 6); + __lasx_xvstelm_w(res, dst, 0, 0); + __lasx_xvstelm_w(res, dst + stride, 0, 1); + __lasx_xvstelm_w(res, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res, dst + stride_3, 0, 5); +} + +static void avc_chroma_vt_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1) +{ + ptrdiff_t stride_2 = stride << 1; + ptrdiff_t stride_3 = stride_2 + stride; + ptrdiff_t stride_4 = stride_2 << 1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src1, src2, src3, src4); + src += stride_4; + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2, src, stride_3, + src, stride_4, src5, src6, src7, src8); + DUP4_ARG2(__lasx_xvilvl_b, src1, src0, src2, src1, src3, src2, src4, src3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lasx_xvilvl_b, src5, src4, src6, src5, src7, src6, src8, src7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + tmp0, tmp2, tmp4, tmp6); + tmp0 = __lasx_xvpermi_q(tmp0, tmp2, 0x02); + tmp4 = __lasx_xvpermi_q(tmp4, tmp6, 0x02); + DUP2_ARG2(__lasx_xvdp2_h_bu, tmp0, coeff_vec, tmp4, coeff_vec, res0, res1); + res0 = __lasx_xvssrarni_bu_h(res1, res0, 6); + __lasx_xvstelm_w(res0, dst, 0, 0); + __lasx_xvstelm_w(res0, dst + stride, 0, 1); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 4); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 5); + dst += stride_4; + __lasx_xvstelm_w(res0, dst, 0, 2); + __lasx_xvstelm_w(res0, dst + stride, 0, 3); + __lasx_xvstelm_w(res0, dst + stride_2, 0, 6); + __lasx_xvstelm_w(res0, dst + stride_3, 0, 7); +} + +static void avc_chroma_vt_4w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (8 == height) { + avc_chroma_vt_4x8_lasx(src, dst, stride, coeff0, coeff1); + } else if (4 == height) { + avc_chroma_vt_4x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (2 == height) { + avc_chroma_vt_4x2_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_vt_8w_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + uint32_t coeff0, uint32_t coeff1, + int32_t height) +{ + if (4 == height) { + avc_chroma_vt_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void copy_width4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + uint32_t tp0, tp1, tp2, tp3, tp4, tp5, tp6, tp7; + + if (8 == height) { + ptrdiff_t stride_2, stride_3, stride_4; + + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "ldx.wu %[tp2], %[src], %[stride_2] \n\t" + "ldx.wu %[tp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.wu %[tp4], %[src], 0 \n\t" + "ldx.wu %[tp5], %[src], %[stride] \n\t" + "ldx.wu %[tp6], %[src], %[stride_2] \n\t" + "ldx.wu %[tp7], %[src], %[stride_3] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + "stx.w %[tp2], %[dst], %[stride_2] \n\t" + "stx.w %[tp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.w %[tp4], %[dst], 0 \n\t" + "stx.w %[tp5], %[dst], %[stride] \n\t" + "stx.w %[tp6], %[dst], %[stride_2] \n\t" + "stx.w %[tp7], %[dst], %[stride_3] \n\t" + : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3), [stride_4]"+&r"(stride_4), + [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1), + [tp2]"+&r"(tp2), [tp3]"+&r"(tp3), [tp4]"+&r"(tp4), [tp5]"+&r"(tp5), + [tp6]"+&r"(tp6), [tp7]"+&r"(tp7) + : [stride]"r"(stride) + : "memory" + ); + } else if (4 == height) { + ptrdiff_t stride_2, stride_3; + + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "ldx.wu %[tp2], %[src], %[stride_2] \n\t" + "ldx.wu %[tp3], %[src], %[stride_3] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + "stx.w %[tp2], %[dst], %[stride_2] \n\t" + "stx.w %[tp3], %[dst], %[stride_3] \n\t" + : [stride_2]"+&r"(stride_2), [stride_3]"+&r"(stride_3), + [src]"+&r"(src), [dst]"+&r"(dst), [tp0]"+&r"(tp0), [tp1]"+&r"(tp1), + [tp2]"+&r"(tp2), [tp3]"+&r"(tp3) + : [stride]"r"(stride) + : "memory" + ); + } else if (2 == height) { + __asm__ volatile ( + "ld.wu %[tp0], %[src], 0 \n\t" + "ldx.wu %[tp1], %[src], %[stride] \n\t" + "st.w %[tp0], %[dst], 0 \n\t" + "stx.w %[tp1], %[dst], %[stride] \n\t" + : [tp0]"+&r"(tp0), [tp1]"+&r"(tp1) + : [src]"r"(src), [dst]"r"(dst), [stride]"r"(stride) + : "memory" + ); + } +} + +static void copy_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + if (8 == height) { + copy_width8x8_lasx(src, dst, stride); + } else if (4 == height) { + copy_width8x4_lasx(src, dst, stride); + } +} + +void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if(x && y) { + avc_chroma_hv_4w_lasx(src, dst, stride, x, (8 - x), y, (8 - y), height); + } else if (x) { + avc_chroma_hz_4w_lasx(src, dst, stride, x, (8 - x), height); + } else if (y) { + avc_chroma_vt_4w_lasx(src, dst, stride, y, (8 - y), height); + } else { + copy_width4_lasx(src, dst, stride, height); + } +} + +void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if (!(x || y)) { + copy_width8_lasx(src, dst, stride, height); + } else if (x && y) { + avc_chroma_hv_8w_lasx(src, dst, stride, x, (8 - x), y, (8 - y), height); + } else if (x) { + avc_chroma_hz_8w_lasx(src, dst, stride, x, (8 - x), height); + } else { + avc_chroma_vt_8w_lasx(src, dst, stride, y, (8 - y), height); + } +} + +static av_always_inline void avc_chroma_hv_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, src4, out; + __m256i res_hz0, res_hz1, res_hz2, res_vt0, res_vt1; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP2_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src1, src3); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP2_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src1, src3); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, res_hz0, res_hz1); + res_hz2 = __lasx_xvdp2_h_bu(src3, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + out = __lasx_xvssrarni_bu_h(res_vt1, res_vt0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hv_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coef_hor0, + uint32_t coef_hor1, uint32_t coef_ver0, + uint32_t coef_ver1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res_hz0, res_hz1, res_hz2, res_hz3, res_hz4; + __m256i res_vt0, res_vt1, res_vt2, res_vt3; + __m256i mask; + __m256i coeff_hz_vec0 = __lasx_xvreplgr2vr_b(coef_hor0); + __m256i coeff_hz_vec1 = __lasx_xvreplgr2vr_b(coef_hor1); + __m256i coeff_vt_vec0 = __lasx_xvreplgr2vr_h(coef_ver0); + __m256i coeff_vt_vec1 = __lasx_xvreplgr2vr_h(coef_ver1); + __m256i coeff_hz_vec = __lasx_xvilvl_b(coeff_hz_vec0, coeff_hz_vec1); + + DUP2_ARG2(__lasx_xvld, chroma_mask_arr, 0, src, 0, mask, src0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, src8); + DUP4_ARG3(__lasx_xvpermi_q, src2, src1, 0x20, src4, src3, 0x20, src6, src5, 0x20, + src8, src7, 0x20, src1, src3, src5, src7); + src0 = __lasx_xvshuf_b(src0, src0, mask); + DUP4_ARG3(__lasx_xvshuf_b, src1, src1, mask, src3, src3, mask, src5, src5, mask, src7, + src7, mask, src1, src3, src5, src7); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_hz_vec, src1, coeff_hz_vec, src3, + coeff_hz_vec, src5, coeff_hz_vec, res_hz0, res_hz1, res_hz2, res_hz3); + res_hz4 = __lasx_xvdp2_h_bu(src7, coeff_hz_vec); + res_vt0 = __lasx_xvmul_h(res_hz1, coeff_vt_vec0); + res_vt1 = __lasx_xvmul_h(res_hz2, coeff_vt_vec0); + res_vt2 = __lasx_xvmul_h(res_hz3, coeff_vt_vec0); + res_vt3 = __lasx_xvmul_h(res_hz4, coeff_vt_vec0); + res_hz0 = __lasx_xvpermi_q(res_hz1, res_hz0, 0x20); + res_hz1 = __lasx_xvpermi_q(res_hz1, res_hz2, 0x3); + res_hz2 = __lasx_xvpermi_q(res_hz2, res_hz3, 0x3); + res_hz3 = __lasx_xvpermi_q(res_hz3, res_hz4, 0x3); + res_vt0 = __lasx_xvmadd_h(res_vt0, res_hz0, coeff_vt_vec1); + res_vt1 = __lasx_xvmadd_h(res_vt1, res_hz1, coeff_vt_vec1); + res_vt2 = __lasx_xvmadd_h(res_vt2, res_hz2, coeff_vt_vec1); + res_vt3 = __lasx_xvmadd_h(res_vt3, res_hz3, coeff_vt_vec1); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res_vt1, res_vt0, 6, res_vt3, res_vt2, 6, + out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, out; + __m256i res0, res1; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + mask = __lasx_xvld(chroma_mask_arr, 0); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + DUP2_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src0, src2); + DUP2_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_hz_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i mask; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + mask = __lasx_xvld(chroma_mask_arr, 0); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src0, src1, src2, src3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src4, src5, src6, src7); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src3, src2, 0x20, src5, src4, 0x20, + src7, src6, 0x20, src0, src2, src4, src6); + DUP4_ARG3(__lasx_xvshuf_b, src0, src0, mask, src2, src2, mask, src4, src4, + mask, src6, src6, mask, src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_and_aver_dst_8x4_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3; + __m256i src0, src1, src2, src3, src4, out; + __m256i res0, res1; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, stride, src, stride_2x, src, stride_3x, src, stride_4x, + src1, src2, src3, src4); + DUP4_ARG3(__lasx_xvpermi_q, src1, src0, 0x20, src2, src1, 0x20, src3, src2, 0x20, + src4, src3, 0x20, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_b, src1, src0, src3, src2, src0, src2); + DUP2_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, res0, res1); + out = __lasx_xvssrarni_bu_h(res1, res0, 6); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + tp0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out = __lasx_xvavgr_bu(out, tp0); + __lasx_xvstelm_d(out, dst, 0, 0); + __lasx_xvstelm_d(out, dst + stride, 0, 2); + __lasx_xvstelm_d(out, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out, dst + stride_3x, 0, 3); +} + +static av_always_inline void avc_chroma_vt_and_aver_dst_8x8_lasx(uint8_t *src, + uint8_t *dst, ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1) +{ + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tp0, tp1, tp2, tp3, dst0, dst1; + __m256i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m256i out0, out1; + __m256i res0, res1, res2, res3; + __m256i coeff_vec0 = __lasx_xvreplgr2vr_b(coeff0); + __m256i coeff_vec1 = __lasx_xvreplgr2vr_b(coeff1); + __m256i coeff_vec = __lasx_xvilvl_b(coeff_vec0, coeff_vec1); + + coeff_vec = __lasx_xvslli_b(coeff_vec, 3); + src0 = __lasx_xvld(src, 0); + src += stride; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src1, src2, src3, src4); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, src, stride_3x, + src5, src6, src7, 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_xvilvl_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src2, src4, src6); + DUP4_ARG2(__lasx_xvdp2_h_bu, src0, coeff_vec, src2, coeff_vec, src4, coeff_vec, src6, + coeff_vec, res0, res1, res2, res3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, res1, res0, 6, res3, res2, 6, out0, out1); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst0 = __lasx_xvpermi_q(tp2, tp0, 0x20); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, dst, stride_3x, + tp0, tp1, tp2, tp3); + dst -= stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tp2, tp0, tp3, tp1, tp0, tp2); + dst1 = __lasx_xvpermi_q(tp2, tp0, 0x20); + out0 = __lasx_xvavgr_bu(out0, dst0); + out1 = __lasx_xvavgr_bu(out1, dst1); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + stride, 0, 2); + __lasx_xvstelm_d(out0, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + stride, 0, 2); + __lasx_xvstelm_d(out1, dst + stride_2x, 0, 1); + __lasx_xvstelm_d(out1, dst + stride_3x, 0, 3); +} + +static av_always_inline void avg_width8x8_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + + src += stride_4x; + dst += stride_4x; + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static av_always_inline void avg_width8x4_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + src0 = __lasx_xvldrepl_d(src, 0); + src1 = __lasx_xvldrepl_d(src + stride, 0); + src2 = __lasx_xvldrepl_d(src + stride_2x, 0); + src3 = __lasx_xvldrepl_d(src + stride_3x, 0); + dst0 = __lasx_xvldrepl_d(dst, 0); + dst1 = __lasx_xvldrepl_d(dst + stride, 0); + dst2 = __lasx_xvldrepl_d(dst + stride_2x, 0); + dst3 = __lasx_xvldrepl_d(dst + stride_3x, 0); + src0 = __lasx_xvpackev_d(src1,src0); + src2 = __lasx_xvpackev_d(src3,src2); + src0 = __lasx_xvpermi_q(src0, src2, 0x02); + dst0 = __lasx_xvpackev_d(dst1,dst0); + dst2 = __lasx_xvpackev_d(dst3,dst2); + dst0 = __lasx_xvpermi_q(dst0, dst2, 0x02); + dst0 = __lasx_xvavgr_bu(src0, dst0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static void avc_chroma_hv_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, + uint32_t coef_hor0, + uint32_t coef_hor1, + uint32_t coef_ver0, + uint32_t coef_ver1, + int32_t height) +{ + if (4 == height) { + avc_chroma_hv_and_aver_dst_8x4_lasx(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } else if (8 == height) { + avc_chroma_hv_and_aver_dst_8x8_lasx(src, dst, stride, coef_hor0, + coef_hor1, coef_ver0, coef_ver1); + } +} + +static void avc_chroma_hz_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_hz_and_aver_dst_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_hz_and_aver_dst_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avc_chroma_vt_and_aver_dst_8w_lasx(uint8_t *src, uint8_t *dst, + ptrdiff_t stride, uint32_t coeff0, + uint32_t coeff1, int32_t height) +{ + if (4 == height) { + avc_chroma_vt_and_aver_dst_8x4_lasx(src, dst, stride, coeff0, coeff1); + } else if (8 == height) { + avc_chroma_vt_and_aver_dst_8x8_lasx(src, dst, stride, coeff0, coeff1); + } +} + +static void avg_width8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t height) +{ + if (8 == height) { + avg_width8x8_lasx(src, dst, stride); + } else if (4 == height) { + avg_width8x4_lasx(src, dst, stride); + } +} + +void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int height, int x, int y) +{ + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + if (!(x || y)) { + avg_width8_lasx(src, dst, stride, height); + } else if (x && y) { + avc_chroma_hv_and_aver_dst_8w_lasx(src, dst, stride, x, (8 - x), y, + (8 - y), height); + } else if (x) { + avc_chroma_hz_and_aver_dst_8w_lasx(src, dst, stride, x, (8 - x), height); + } else { + avc_chroma_vt_and_aver_dst_8w_lasx(src, dst, stride, y, (8 - y), height); + } +} diff --git a/libavcodec/loongarch/h264chroma_lasx.h b/libavcodec/loongarch/h264chroma_lasx.h new file mode 100644 index 0000000000..4aac8db8cb --- /dev/null +++ b/libavcodec/loongarch/h264chroma_lasx.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2020 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_H264CHROMA_LASX_H +#define AVCODEC_LOONGARCH_H264CHROMA_LASX_H + +#include +#include +#include "libavcodec/h264.h" + +void ff_put_h264_chroma_mc4_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_put_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); +void ff_avg_h264_chroma_mc8_lasx(uint8_t *dst, uint8_t *src, ptrdiff_t stride, + int h, int x, int y); + +#endif /* AVCODEC_LOONGARCH_H264CHROMA_LASX_H */ diff --git a/libavcodec/loongarch/h264dsp_init_loongarch.c b/libavcodec/loongarch/h264dsp_init_loongarch.c new file mode 100644 index 0000000000..37633c3e51 --- /dev/null +++ b/libavcodec/loongarch/h264dsp_init_loongarch.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * 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 "libavutil/loongarch/cpu.h" +#include "h264dsp_lasx.h" + +av_cold void ff_h264dsp_init_loongarch(H264DSPContext *c, const int bit_depth, + const int chroma_format_idc) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + if (chroma_format_idc <= 1) + c->h264_loop_filter_strength = ff_h264_loop_filter_strength_lasx; + if (bit_depth == 8) { + c->h264_add_pixels4_clear = ff_h264_add_pixels4_8_lasx; + c->h264_add_pixels8_clear = ff_h264_add_pixels8_8_lasx; + c->h264_v_loop_filter_luma = ff_h264_v_lpf_luma_8_lasx; + c->h264_h_loop_filter_luma = ff_h264_h_lpf_luma_8_lasx; + c->h264_v_loop_filter_luma_intra = ff_h264_v_lpf_luma_intra_8_lasx; + c->h264_h_loop_filter_luma_intra = ff_h264_h_lpf_luma_intra_8_lasx; + c->h264_v_loop_filter_chroma = ff_h264_v_lpf_chroma_8_lasx; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma = ff_h264_h_lpf_chroma_8_lasx; + c->h264_v_loop_filter_chroma_intra = ff_h264_v_lpf_chroma_intra_8_lasx; + + if (chroma_format_idc <= 1) + c->h264_h_loop_filter_chroma_intra = ff_h264_h_lpf_chroma_intra_8_lasx; + + /* Weighted MC */ + c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels16_8_lasx; + c->weight_h264_pixels_tab[1] = ff_weight_h264_pixels8_8_lasx; + c->weight_h264_pixels_tab[2] = ff_weight_h264_pixels4_8_lasx; + + c->biweight_h264_pixels_tab[0] = ff_biweight_h264_pixels16_8_lasx; + c->biweight_h264_pixels_tab[1] = ff_biweight_h264_pixels8_8_lasx; + c->biweight_h264_pixels_tab[2] = ff_biweight_h264_pixels4_8_lasx; + + c->h264_idct_add = ff_h264_idct_add_lasx; + c->h264_idct8_add = ff_h264_idct8_addblk_lasx; + c->h264_idct_dc_add = ff_h264_idct4x4_addblk_dc_lasx; + c->h264_idct8_dc_add = ff_h264_idct8_dc_addblk_lasx; + c->h264_idct_add16 = ff_h264_idct_add16_lasx; + c->h264_idct8_add4 = ff_h264_idct8_add4_lasx; + + if (chroma_format_idc <= 1) + c->h264_idct_add8 = ff_h264_idct_add8_lasx; + else + c->h264_idct_add8 = ff_h264_idct_add8_422_lasx; + + c->h264_idct_add16intra = ff_h264_idct_add16_intra_lasx; + c->h264_luma_dc_dequant_idct = ff_h264_deq_idct_luma_dc_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264dsp_lasx.c b/libavcodec/loongarch/h264dsp_lasx.c new file mode 100644 index 0000000000..7fd4cedf7e --- /dev/null +++ b/libavcodec/loongarch/h264dsp_lasx.c @@ -0,0 +1,2114 @@ +/* + * Loongson LASX optimized h264dsp + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * 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 "libavutil/loongarch/loongson_intrinsics.h" +#include "h264dsp_lasx.h" + +#define AVC_LPF_P1_OR_Q1(p0_or_q0_org_in, q0_or_p0_org_in, \ + p1_or_q1_org_in, p2_or_q2_org_in, \ + neg_tc_in, tc_in, p1_or_q1_out) \ +{ \ + __m256i clip3, temp; \ + \ + clip3 = __lasx_xvavgr_hu(p0_or_q0_org_in, \ + q0_or_p0_org_in); \ + temp = __lasx_xvslli_h(p1_or_q1_org_in, 1); \ + clip3 = __lasx_xvsub_h(clip3, temp); \ + clip3 = __lasx_xvavg_h(p2_or_q2_org_in, clip3); \ + clip3 = __lasx_xvclip_h(clip3, neg_tc_in, tc_in); \ + p1_or_q1_out = __lasx_xvadd_h(p1_or_q1_org_in, clip3); \ +} + +#define AVC_LPF_P0Q0(q0_or_p0_org_in, p0_or_q0_org_in, \ + p1_or_q1_org_in, q1_or_p1_org_in, \ + neg_threshold_in, threshold_in, \ + p0_or_q0_out, q0_or_p0_out) \ +{ \ + __m256i q0_sub_p0, p1_sub_q1, delta; \ + \ + q0_sub_p0 = __lasx_xvsub_h(q0_or_p0_org_in, \ + p0_or_q0_org_in); \ + p1_sub_q1 = __lasx_xvsub_h(p1_or_q1_org_in, \ + q1_or_p1_org_in); \ + q0_sub_p0 = __lasx_xvslli_h(q0_sub_p0, 2); \ + p1_sub_q1 = __lasx_xvaddi_hu(p1_sub_q1, 4); \ + delta = __lasx_xvadd_h(q0_sub_p0, p1_sub_q1); \ + delta = __lasx_xvsrai_h(delta, 3); \ + delta = __lasx_xvclip_h(delta, neg_threshold_in, \ + threshold_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_org_in, delta); \ + q0_or_p0_out = __lasx_xvsub_h(q0_or_p0_org_in, delta); \ + \ + p0_or_q0_out = __lasx_xvclip255_h(p0_or_q0_out); \ + q0_or_p0_out = __lasx_xvclip255_h(q0_or_p0_out); \ +} + +void ff_h264_h_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_8x = img_width << 3; + ptrdiff_t img_width_3x = img_width_2x + img_width; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, + 0x0101010100000000, 0x0303030302020202}; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + + if (__lasx_xbnz_v(bs_vec)) { + uint8_t *src = data - 4; + __m256i p3_org, p2_org, p1_org, p0_org, q0_org, q1_org, q2_org, q3_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + __m256i zero = __lasx_xvldi(0); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + + { + uint8_t *src_tmp = src + img_width_8x; + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i row8, row9, row10, row11, row12, row13, row14, row15; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src -= img_width_4x; + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, img_width, src_tmp, + img_width_2x, src_tmp, img_width_3x, + row8, row9, row10, row11); + src_tmp += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, img_width, src_tmp, + img_width_2x, src_tmp, img_width_3x, + row12, row13, row14, row15); + src_tmp -= img_width_4x; + + LASX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, + row7, row8, row9, row10, row11, + row12, row13, row14, row15, + p3_org, p2_org, p1_org, p0_org, + q0_org, q1_org, q2_org, q3_org); + } + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i neg_tc_h, tc_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i p2_asub_p0, q2_asub_q0; + + neg_tc_h = __lasx_xvneg_b(tc_vec); + neg_tc_h = __lasx_vext2xv_h_b(neg_tc_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p1_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, p1_org_h, p2_org_h, + neg_tc_h, tc_h, p1_h); + p1_h = __lasx_xvpickev_b(p1_h, p1_h); + p1_h = __lasx_xvpermi_d(p1_h, 0xd8); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q1_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, q1_org_h, q2_org_h, + neg_tc_h, tc_h, q1_h); + q1_h = __lasx_xvpickev_b(q1_h, q1_h); + q1_h = __lasx_xvpermi_d(q1_h, 0xd8); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + { + __m256i neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i control = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + + DUP4_ARG3(__lasx_xvpermi_q, p0_org, q3_org, 0x02, p1_org, + q2_org, 0x02, p2_org, q1_org, 0x02, p3_org, + q0_org, 0x02, p0_org, p1_org, p2_org, p3_org); + DUP2_ARG2(__lasx_xvilvl_b, p1_org, p3_org, p0_org, p2_org, + row0, row2); + DUP2_ARG2(__lasx_xvilvh_b, p1_org, p3_org, p0_org, p2_org, + row1, row3); + DUP2_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row4, row6); + DUP2_ARG2(__lasx_xvilvh_b, row2, row0, row3, row1, row5, row7); + DUP4_ARG2(__lasx_xvperm_w, row4, control, row5, control, row6, + control, row7, control, row4, row5, row6, row7); + __lasx_xvstelm_d(row4, src, 0, 0); + __lasx_xvstelm_d(row4, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row4, src, 0, 2); + __lasx_xvstelm_d(row4, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 0); + __lasx_xvstelm_d(row5, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 2); + __lasx_xvstelm_d(row5, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 0); + __lasx_xvstelm_d(row6, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 2); + __lasx_xvstelm_d(row6, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 0); + __lasx_xvstelm_d(row7, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 2); + __lasx_xvstelm_d(row7, src + img_width, 0, 3); + } + } + } +} + +void ff_h264_v_lpf_luma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_3x = img_width + img_width_2x; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0101010100000000, 0x0303030302020202, + 0x0101010100000000, 0x0303030302020202}; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + + if (__lasx_xbnz_v(bs_vec)) { + __m256i p2_org, p1_org, p0_org, q0_org, q1_org, q2_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i is_bs_greater_than0; + __m256i zero = __lasx_xvldi(0); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + DUP2_ARG2(__lasx_xvldx, data, -img_width_3x, data, -img_width_2x, + p2_org, p1_org); + p0_org = __lasx_xvldx(data, -img_width); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i neg_tc_h, tc_h, p2_asub_p0, q2_asub_q0; + + q2_org = __lasx_xvldx(data, img_width_2x); + + neg_tc_h = __lasx_xvneg_b(tc_vec); + neg_tc_h = __lasx_vext2xv_h_b(neg_tc_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p1_h, p2_org_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, p1_org_h, p2_org_h, + neg_tc_h, tc_h, p1_h); + p1_h = __lasx_xvpickev_b(p1_h, p1_h); + p1_h = __lasx_xvpermi_d(p1_h, 0xd8); + p1_h = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p1_org = __lasx_xvpermi_q(p1_org, p1_h, 0x30); + __lasx_xvst(p1_org, data - img_width_2x, 0); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + } + + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & is_less_than; + + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q1_h, q2_org_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + AVC_LPF_P1_OR_Q1(p0_org_h, q0_org_h, q1_org_h, q2_org_h, + neg_tc_h, tc_h, q1_h); + q1_h = __lasx_xvpickev_b(q1_h, q1_h); + q1_h = __lasx_xvpermi_d(q1_h, 0xd8); + q1_h = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q1_org = __lasx_xvpermi_q(q1_org, q1_h, 0x30); + __lasx_xvst(q1_org, data + img_width, 0); + + is_less_than_beta = __lasx_xvandi_b(is_less_than_beta, 1); + tc_vec = __lasx_xvadd_b(tc_vec, is_less_than_beta); + + } + + { + __m256i neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0Xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + p0_org = __lasx_xvpermi_q(p0_org, p0_h, 0x30); + q0_org = __lasx_xvpermi_q(q0_org, q0_h, 0x30); + __lasx_xvst(p0_org, data - img_width, 0); + __lasx_xvst(q0_org, data, 0); + } + } + } +} + +void ff_h264_h_lpf_chroma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0303020201010000, 0x0303020201010000, 0x0, 0x0}; + __m256i zero = __lasx_xvldi(0); + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + bs_vec = __lasx_xvpermi_q(zero, bs_vec, 0x30); + + if (__lasx_xbnz_v(bs_vec)) { + uint8_t *src = data - 2; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src -= img_width_4x; + /* LASX_TRANSPOSE8x4_B */ + DUP4_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row6, row4, + row7, row5, p1_org, p0_org, q0_org, q1_org); + row0 = __lasx_xvilvl_b(p0_org, p1_org); + row1 = __lasx_xvilvl_b(q1_org, q0_org); + row3 = __lasx_xvilvh_w(row1, row0); + row2 = __lasx_xvilvl_w(row1, row0); + p1_org = __lasx_xvpermi_d(row2, 0x00); + p0_org = __lasx_xvpermi_d(row2, 0x55); + q0_org = __lasx_xvpermi_d(row3, 0x00); + q1_org = __lasx_xvpermi_d(row3, 0x55); + } + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + { + __m256i tc_h, neg_thresh_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + + p0_org = __lasx_xvilvl_b(q0_org, p0_org); + src = data - 1; + __lasx_xvstelm_h(p0_org, src, 0, 0); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 1); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 2); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 3); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 4); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 5); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 6); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 7); + } + } +} + +void ff_h264_v_lpf_chroma_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in, int8_t *tc) +{ + int img_width_2x = img_width << 1; + __m256i tmp_vec0, bs_vec; + __m256i tc_vec = {0x0303020201010000, 0x0303020201010000, 0x0, 0x0}; + __m256i zero = __lasx_xvldi(0); + + tmp_vec0 = __lasx_xvldrepl_w((uint32_t*)tc, 0); + tc_vec = __lasx_xvshuf_b(tmp_vec0, tmp_vec0, tc_vec); + bs_vec = __lasx_xvslti_b(tc_vec, 0); + bs_vec = __lasx_xvxori_b(bs_vec, 255); + bs_vec = __lasx_xvandi_b(bs_vec, 1); + bs_vec = __lasx_xvpermi_q(zero, bs_vec, 0x30); + + if (__lasx_xbnz_v(bs_vec)) { + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i is_bs_greater_than0; + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + DUP2_ARG2(__lasx_xvldx, data, -img_width_2x, data, -img_width, + p1_org, p0_org); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + is_bs_greater_than0 = __lasx_xvslt_bu(zero, bs_vec); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = is_less_than & is_bs_greater_than0; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + { + __m256i neg_thresh_h, tc_h, p0_h, q0_h; + + neg_thresh_h = __lasx_xvneg_b(tc_vec); + neg_thresh_h = __lasx_vext2xv_h_b(neg_thresh_h); + tc_h = __lasx_vext2xv_hu_bu(tc_vec); + + AVC_LPF_P0Q0(q0_org_h, p0_org_h, p1_org_h, q1_org_h, + neg_thresh_h, tc_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, + p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, + p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + __lasx_xvstelm_d(p0_h, data - img_width, 0, 0); + __lasx_xvstelm_d(q0_h, data, 0, 0); + } + } + } +} + +#define AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_or_q3_org_in, p0_or_q0_org_in, \ + q3_or_p3_org_in, p1_or_q1_org_in, \ + p2_or_q2_org_in, q1_or_p1_org_in, \ + p0_or_q0_out, p1_or_q1_out, p2_or_q2_out) \ +{ \ + __m256i threshold; \ + __m256i const2, const3 = __lasx_xvldi(0); \ + \ + const2 = __lasx_xvaddi_hu(const3, 2); \ + const3 = __lasx_xvaddi_hu(const3, 3); \ + threshold = __lasx_xvadd_h(p0_or_q0_org_in, q3_or_p3_org_in); \ + threshold = __lasx_xvadd_h(p1_or_q1_org_in, threshold); \ + \ + p0_or_q0_out = __lasx_xvslli_h(threshold, 1); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p2_or_q2_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, q1_or_p1_org_in); \ + p0_or_q0_out = __lasx_xvsrar_h(p0_or_q0_out, const3); \ + \ + p1_or_q1_out = __lasx_xvadd_h(p2_or_q2_org_in, threshold); \ + p1_or_q1_out = __lasx_xvsrar_h(p1_or_q1_out, const2); \ + \ + p2_or_q2_out = __lasx_xvmul_h(p2_or_q2_org_in, const3); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, p3_or_q3_org_in); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, p3_or_q3_org_in); \ + p2_or_q2_out = __lasx_xvadd_h(p2_or_q2_out, threshold); \ + p2_or_q2_out = __lasx_xvsrar_h(p2_or_q2_out, const3); \ +} + +/* data[-u32_img_width] = (uint8_t)((2 * p1 + p0 + q1 + 2) >> 2); */ +#define AVC_LPF_P0_OR_Q0(p0_or_q0_org_in, q1_or_p1_org_in, \ + p1_or_q1_org_in, p0_or_q0_out) \ +{ \ + __m256i const2 = __lasx_xvldi(0); \ + const2 = __lasx_xvaddi_hu(const2, 2); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_org_in, q1_or_p1_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p1_or_q1_org_in); \ + p0_or_q0_out = __lasx_xvadd_h(p0_or_q0_out, p1_or_q1_org_in); \ + p0_or_q0_out = __lasx_xvsrar_h(p0_or_q0_out, const2); \ +} + +void ff_h264_h_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + uint8_t *src = data - 4; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p3_org, p2_org, p1_org, p0_org, q0_org, q1_org, q2_org, q3_org; + __m256i zero = __lasx_xvldi(0); + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i row8, row9, row10, row11, row12, row13, row14, row15; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row4, row5, row6, row7); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row8, row9, row10, row11); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, row12, row13, row14, row15); + src += img_width_4x; + + LASX_TRANSPOSE16x8_B(row0, row1, row2, row3, + row4, row5, row6, row7, + row8, row9, row10, row11, + row12, row13, row14, row15, + p3_org, p2_org, p1_org, p0_org, + q0_org, q1_org, q2_org, q3_org); + } + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_beta & is_less_than_alpha; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = __lasx_xvpermi_q(zero, is_less_than, 0x30); + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p2_asub_p0, q2_asub_q0, p0_h, q0_h, negate_is_less_than_beta; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i less_alpha_shift2_add2 = __lasx_xvsrli_b(alpha, 2); + + less_alpha_shift2_add2 = __lasx_xvaddi_bu(less_alpha_shift2_add2, 2); + less_alpha_shift2_add2 = __lasx_xvslt_bu(p0_asub_q0, + less_alpha_shift2_add2); + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p3_org_h, p1_h, p2_h; + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + p3_org_h = __lasx_vext2xv_hu_bu(p3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_org_h, p0_org_h, q0_org_h, p1_org_h, + p2_org_h, q1_org_h, p0_h, p1_h, p2_h); + + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, p1_h, p1_h, p2_h, p2_h, p1_h, p2_h); + DUP2_ARG2(__lasx_xvpermi_d, p1_h, 0xd8, p2_h, 0xd8, p1_h, p2_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than_beta); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p2_org = __lasx_xvbitsel_v(p2_org, p2_h, is_less_than_beta); + } + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + /* combine */ + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, negate_is_less_than_beta); + + /* if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta_in) */ + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q3_org_h, q1_h, q2_h; + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + q3_org_h = __lasx_vext2xv_hu_bu(q3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(q3_org_h, q0_org_h, p0_org_h, q1_org_h, + q2_org_h, p1_org_h, q0_h, q1_h, q2_h); + + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, q1_h, q1_h, q2_h, q2_h, q1_h, q2_h); + DUP2_ARG2(__lasx_xvpermi_d, q1_h, 0xd8, q2_h, 0xd8, q1_h, q2_h); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than_beta); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q2_org = __lasx_xvbitsel_v(q2_org, q2_h, is_less_than_beta); + + } + + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + + /* combine */ + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, negate_is_less_than_beta); + + /* transpose and store */ + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + __m256i control = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + + DUP4_ARG3(__lasx_xvpermi_q, p0_org, q3_org, 0x02, p1_org, q2_org, + 0x02, p2_org, q1_org, 0x02, p3_org, q0_org, 0x02, + p0_org, p1_org, p2_org, p3_org); + DUP2_ARG2(__lasx_xvilvl_b, p1_org, p3_org, p0_org, p2_org, + row0, row2); + DUP2_ARG2(__lasx_xvilvh_b, p1_org, p3_org, p0_org, p2_org, + row1, row3); + DUP2_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row4, row6); + DUP2_ARG2(__lasx_xvilvh_b, row2, row0, row3, row1, row5, row7); + DUP4_ARG2(__lasx_xvperm_w, row4, control, row5, control, row6, + control, row7, control, row4, row5, row6, row7); + src = data - 4; + __lasx_xvstelm_d(row4, src, 0, 0); + __lasx_xvstelm_d(row4, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row4, src, 0, 2); + __lasx_xvstelm_d(row4, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 0); + __lasx_xvstelm_d(row5, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row5, src, 0, 2); + __lasx_xvstelm_d(row5, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 0); + __lasx_xvstelm_d(row6, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row6, src, 0, 2); + __lasx_xvstelm_d(row6, src + img_width, 0, 3); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 0); + __lasx_xvstelm_d(row7, src + img_width, 0, 1); + src += img_width_2x; + __lasx_xvstelm_d(row7, src, 0, 2); + __lasx_xvstelm_d(row7, src + img_width, 0, 3); + } + } +} + +void ff_h264_v_lpf_luma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_3x = img_width_2x + img_width; + uint8_t *src = data - img_width_2x; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i zero = __lasx_xvldi(0); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, + src, img_width_3x, p1_org, p0_org, q0_org, q1_org); + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_beta & is_less_than_alpha; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + is_less_than = __lasx_xvpermi_q(zero, is_less_than, 0x30); + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p2_asub_p0, q2_asub_q0, p0_h, q0_h, negate_is_less_than_beta; + __m256i p1_org_h, p0_org_h, q0_org_h, q1_org_h; + __m256i p2_org = __lasx_xvldx(src, -img_width); + __m256i q2_org = __lasx_xvldx(data, img_width_2x); + __m256i less_alpha_shift2_add2 = __lasx_xvsrli_b(alpha, 2); + less_alpha_shift2_add2 = __lasx_xvaddi_bu(less_alpha_shift2_add2, 2); + less_alpha_shift2_add2 = __lasx_xvslt_bu(p0_asub_q0, + less_alpha_shift2_add2); + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + p2_asub_p0 = __lasx_xvabsd_bu(p2_org, p0_org); + is_less_than_beta = __lasx_xvslt_bu(p2_asub_p0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i p2_org_h, p3_org_h, p1_h, p2_h; + __m256i p3_org = __lasx_xvldx(src, -img_width_2x); + + p2_org_h = __lasx_vext2xv_hu_bu(p2_org); + p3_org_h = __lasx_vext2xv_hu_bu(p3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(p3_org_h, p0_org_h, q0_org_h, p1_org_h, + p2_org_h, q1_org_h, p0_h, p1_h, p2_h); + + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, p1_h, p1_h, p2_h, p2_h, p1_h, p2_h); + DUP2_ARG2(__lasx_xvpermi_d, p1_h, 0xd8, p2_h, 0xd8, p1_h, p2_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than_beta); + p1_org = __lasx_xvbitsel_v(p1_org, p1_h, is_less_than_beta); + p2_org = __lasx_xvbitsel_v(p2_org, p2_h, is_less_than_beta); + + __lasx_xvst(p1_org, src, 0); + __lasx_xvst(p2_org, src - img_width, 0); + } + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + /* combine */ + p0_h = __lasx_xvpickev_b(p0_h, p0_h); + p0_h = __lasx_xvpermi_d(p0_h, 0xd8); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, negate_is_less_than_beta); + __lasx_xvst(p0_org, data - img_width, 0); + + /* if (tmpFlag && (unsigned)ABS(q2-q0) < thresholds->beta_in) */ + q2_asub_q0 = __lasx_xvabsd_bu(q2_org, q0_org); + is_less_than_beta = __lasx_xvslt_bu(q2_asub_q0, beta); + is_less_than_beta = is_less_than_beta & less_alpha_shift2_add2; + negate_is_less_than_beta = __lasx_xvxori_b(is_less_than_beta, 0xff); + is_less_than_beta = is_less_than_beta & is_less_than; + negate_is_less_than_beta = negate_is_less_than_beta & is_less_than; + + /* combine and store */ + if (__lasx_xbnz_v(is_less_than_beta)) { + __m256i q2_org_h, q3_org_h, q1_h, q2_h; + __m256i q3_org = __lasx_xvldx(data, img_width_2x + img_width); + + q2_org_h = __lasx_vext2xv_hu_bu(q2_org); + q3_org_h = __lasx_vext2xv_hu_bu(q3_org); + + AVC_LPF_P0P1P2_OR_Q0Q1Q2(q3_org_h, q0_org_h, p0_org_h, q1_org_h, + q2_org_h, p1_org_h, q0_h, q1_h, q2_h); + + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + DUP2_ARG2(__lasx_xvpickev_b, q1_h, q1_h, q2_h, q2_h, q1_h, q2_h); + DUP2_ARG2(__lasx_xvpermi_d, q1_h, 0xd8, q2_h, 0xd8, q1_h, q2_h); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than_beta); + q1_org = __lasx_xvbitsel_v(q1_org, q1_h, is_less_than_beta); + q2_org = __lasx_xvbitsel_v(q2_org, q2_h, is_less_than_beta); + + __lasx_xvst(q1_org, data + img_width, 0); + __lasx_xvst(q2_org, data + img_width_2x, 0); + } + + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + + /* combine */ + q0_h = __lasx_xvpickev_b(q0_h, q0_h); + q0_h = __lasx_xvpermi_d(q0_h, 0xd8); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, negate_is_less_than_beta); + + __lasx_xvst(q0_org, data, 0); + } +} + +void ff_h264_h_lpf_chroma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + uint8_t *src = data - 2; + ptrdiff_t img_width_2x = img_width << 1; + ptrdiff_t img_width_4x = img_width << 2; + ptrdiff_t img_width_3x = img_width_2x + img_width; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + + { + __m256i row0, row1, row2, row3, row4, row5, row6, row7; + + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, src, + img_width_3x, row0, row1, row2, row3); + src += img_width_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, img_width, src, img_width_2x, src, + img_width_3x, row4, row5, row6, row7); + + /* LASX_TRANSPOSE8x4_B */ + DUP4_ARG2(__lasx_xvilvl_b, row2, row0, row3, row1, row6, row4, row7, row5, + p1_org, p0_org, q0_org, q1_org); + row0 = __lasx_xvilvl_b(p0_org, p1_org); + row1 = __lasx_xvilvl_b(q1_org, q0_org); + row3 = __lasx_xvilvh_w(row1, row0); + row2 = __lasx_xvilvl_w(row1, row0); + p1_org = __lasx_xvpermi_d(row2, 0x00); + p0_org = __lasx_xvpermi_d(row2, 0x55); + q0_org = __lasx_xvpermi_d(row3, 0x00); + q1_org = __lasx_xvpermi_d(row3, 0x55); + } + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p0_h, q0_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, p0_h, q0_h); + p0_org = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_org = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + } + p0_org = __lasx_xvilvl_b(q0_org, p0_org); + src = data - 1; + __lasx_xvstelm_h(p0_org, src, 0, 0); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 1); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 2); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 3); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 4); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 5); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 6); + src += img_width; + __lasx_xvstelm_h(p0_org, src, 0, 7); +} + +void ff_h264_v_lpf_chroma_intra_8_lasx(uint8_t *data, ptrdiff_t img_width, + int alpha_in, int beta_in) +{ + ptrdiff_t img_width_2x = img_width << 1; + __m256i p1_org, p0_org, q0_org, q1_org; + __m256i p0_asub_q0, p1_asub_p0, q1_asub_q0, alpha, beta; + __m256i is_less_than, is_less_than_beta, is_less_than_alpha; + + alpha = __lasx_xvreplgr2vr_b(alpha_in); + beta = __lasx_xvreplgr2vr_b(beta_in); + + p1_org = __lasx_xvldx(data, -img_width_2x); + p0_org = __lasx_xvldx(data, -img_width); + DUP2_ARG2(__lasx_xvldx, data, 0, data, img_width, q0_org, q1_org); + + p0_asub_q0 = __lasx_xvabsd_bu(p0_org, q0_org); + p1_asub_p0 = __lasx_xvabsd_bu(p1_org, p0_org); + q1_asub_q0 = __lasx_xvabsd_bu(q1_org, q0_org); + + is_less_than_alpha = __lasx_xvslt_bu(p0_asub_q0, alpha); + is_less_than_beta = __lasx_xvslt_bu(p1_asub_p0, beta); + is_less_than = is_less_than_alpha & is_less_than_beta; + is_less_than_beta = __lasx_xvslt_bu(q1_asub_q0, beta); + is_less_than = is_less_than_beta & is_less_than; + + if (__lasx_xbnz_v(is_less_than)) { + __m256i p0_h, q0_h, p1_org_h, p0_org_h, q0_org_h, q1_org_h; + + p1_org_h = __lasx_vext2xv_hu_bu(p1_org); + p0_org_h = __lasx_vext2xv_hu_bu(p0_org); + q0_org_h = __lasx_vext2xv_hu_bu(q0_org); + q1_org_h = __lasx_vext2xv_hu_bu(q1_org); + + AVC_LPF_P0_OR_Q0(p0_org_h, q1_org_h, p1_org_h, p0_h); + AVC_LPF_P0_OR_Q0(q0_org_h, p1_org_h, q1_org_h, q0_h); + DUP2_ARG2(__lasx_xvpickev_b, p0_h, p0_h, q0_h, q0_h, p0_h, q0_h); + DUP2_ARG2(__lasx_xvpermi_d, p0_h, 0xd8, q0_h, 0xd8, p0_h, q0_h); + p0_h = __lasx_xvbitsel_v(p0_org, p0_h, is_less_than); + q0_h = __lasx_xvbitsel_v(q0_org, q0_h, is_less_than); + __lasx_xvstelm_d(p0_h, data - img_width, 0, 0); + __lasx_xvstelm_d(q0_h, data, 0, 0); + } +} + +void ff_biweight_h264_pixels16_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset_in) +{ + __m256i wgt; + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3; + __m256i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i denom, offset; + int stride_2x = stride << 1; + int stride_4x = stride << 2; + int stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src += stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, dst0, dst1, dst2, dst3); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + dst0, dst1, dst2, dst3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst0, dst, 0, 2); + __lasx_xvstelm_d(dst0, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 2); + __lasx_xvstelm_d(dst1, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 2); + __lasx_xvstelm_d(dst2, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 2); + __lasx_xvstelm_d(dst3, dst, 8, 3); + dst += stride; + + if (16 == height) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src += stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, dst0, dst1, dst2, dst3); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, + tmp6, dst0, dst1, dst2, dst3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst0, dst, 0, 2); + __lasx_xvstelm_d(dst0, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst1, dst, 0, 2); + __lasx_xvstelm_d(dst1, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst2, dst, 0, 2); + __lasx_xvstelm_d(dst2, dst, 8, 3); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(dst3, dst, 0, 2); + __lasx_xvstelm_d(dst3, dst, 8, 3); + } +} + +static void avc_biwgt_8x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + vec1 = __lasx_xvilvh_b(dst0, src0); + DUP2_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + tmp0, tmp1); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + DUP2_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp0, tmp1); + dst0 = __lasx_xvpickev_b(tmp1, tmp0); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); +} + +static void avc_biwgt_8x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1, vec2, vec3; + __m256i src0, src1, dst0, dst1; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t* dst_tmp = dst; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + tmp0 = __lasx_xvld(dst_tmp, 0); + DUP2_ARG2(__lasx_xvldx, dst_tmp, stride, dst_tmp, stride_2x, tmp1, tmp2); + tmp3 = __lasx_xvldx(dst_tmp, stride_3x); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, dst0, 128, dst1, 128, + src0, src1, dst0, dst1); + DUP2_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, vec0, vec2); + DUP2_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, vec1, vec3); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, dst0, dst1); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + stride, 0, 1); + __lasx_xvstelm_d(dst1, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst1, dst + stride_3x, 0, 3); +} + +static void avc_biwgt_8x16_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m256i src0, src1, src2, src3, dst0, dst1, dst2, dst3; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + uint8_t* dst_tmp = dst; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst_tmp, 0, dst_tmp, stride, dst_tmp, stride_2x, + dst_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvxori_b, dst0, 128, dst1, 128, dst2, 128, dst3, 128, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec0, vec2, vec4, vec6); + DUP4_ARG2(__lasx_xvilvh_b, dst0, src0, dst1, src1, dst2, src2, + dst3, src3, vec1, vec3, vec5, vec7); + DUP4_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + offset, wgt, vec2, offset, wgt, vec3, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lasx_xvdp2add_h_b,offset, wgt, vec4, offset, wgt, vec5, + offset, wgt, vec6, offset, wgt, vec7, tmp4, tmp5, tmp6, tmp7); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + tmp2 = __lasx_xvsra_h(tmp2, denom); + tmp3 = __lasx_xvsra_h(tmp3, denom); + tmp4 = __lasx_xvsra_h(tmp4, denom); + tmp5 = __lasx_xvsra_h(tmp5, denom); + tmp6 = __lasx_xvsra_h(tmp6, denom); + tmp7 = __lasx_xvsra_h(tmp7, denom); + DUP4_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp2, tmp3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_xvclip255_h, tmp4, tmp5, tmp6, tmp7, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvpickev_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp4, tmp7, tmp6, + dst0, dst1, dst2, dst3) + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + stride, 0, 1); + __lasx_xvstelm_d(dst0, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + stride, 0, 1); + __lasx_xvstelm_d(dst1, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst1, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst + stride, 0, 1); + __lasx_xvstelm_d(dst2, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst2, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_d(dst3, dst, 0, 0); + __lasx_xvstelm_d(dst3, dst + stride, 0, 1); + __lasx_xvstelm_d(dst3, dst + stride_2x, 0, 2); + __lasx_xvstelm_d(dst3, dst + stride_3x, 0, 3); +} + +void ff_biweight_h264_pixels8_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset) +{ + if (4 == height) { + avc_biwgt_8x4_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } else if (8 == height) { + avc_biwgt_8x8_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } else { + avc_biwgt_8x16_lasx(src, dst, stride, log2_denom, weight_src, weight_dst, + offset); + } +} + +static void avc_biwgt_4x2_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0; + __m256i src0, dst0; + __m256i tmp0, tmp1, denom, offset; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP2_ARG2(__lasx_xvldx, src, 0, src, stride, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvldx, dst, 0, dst, stride, tmp0, tmp1); + dst0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + tmp0 = __lasx_xvdp2add_h_b(offset, wgt, vec0); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp0 = __lasx_xvclip255_h(tmp0); + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); +} + +static void avc_biwgt_4x4_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + dst0 = __lasx_xvilvl_w(tmp1, tmp0); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + dst0 = __lasx_xvilvh_b(dst0, src0); + vec0 = __lasx_xvpermi_q(vec0, dst0, 0x02); + tmp0 = __lasx_xvdp2add_h_b(offset, wgt, vec0); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp0 = __lasx_xvclip255_h(tmp0); + tmp0 = __lasx_xvpickev_b(tmp0, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 4); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 5); +} + +static void avc_biwgt_4x8_lasx(uint8_t *src, uint8_t *dst, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t weight_dst, int32_t offset_in) +{ + __m256i wgt, vec0, vec1; + __m256i src0, dst0; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_in = (unsigned) ((offset_in + 1) | 1) << log2_denom; + offset_in += ((weight_src + weight_dst) << 7); + log2_denom += 1; + + tmp0 = __lasx_xvreplgr2vr_b(weight_src); + tmp1 = __lasx_xvreplgr2vr_b(weight_dst); + wgt = __lasx_xvilvh_b(tmp1, tmp0); + offset = __lasx_xvreplgr2vr_h(offset_in); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, tmp5, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp0, tmp1, tmp2, tmp3); + dst += stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, stride, dst, stride_2x, + dst, stride_3x, tmp4, tmp5, tmp6, tmp7); + dst -= stride_4x; + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, tmp5, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + dst0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvxori_b, src0, 128, dst0, 128, src0, dst0); + vec0 = __lasx_xvilvl_b(dst0, src0); + vec1 = __lasx_xvilvh_b(dst0, src0); + DUP2_ARG3(__lasx_xvdp2add_h_b, offset, wgt, vec0, offset, wgt, vec1, + tmp0, tmp1); + tmp0 = __lasx_xvsra_h(tmp0, denom); + tmp1 = __lasx_xvsra_h(tmp1, denom); + DUP2_ARG1(__lasx_xvclip255_h, tmp0, tmp1, tmp0, tmp1); + tmp0 = __lasx_xvpickev_b(tmp1, tmp0); + __lasx_xvstelm_w(tmp0, dst, 0, 0); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 2); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 3); + dst += stride_4x; + __lasx_xvstelm_w(tmp0, dst, 0, 4); + __lasx_xvstelm_w(tmp0, dst + stride, 0, 5); + __lasx_xvstelm_w(tmp0, dst + stride_2x, 0, 6); + __lasx_xvstelm_w(tmp0, dst + stride_3x, 0, 7); +} + +void ff_biweight_h264_pixels4_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset) +{ + if (2 == height) { + avc_biwgt_4x2_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } else if (4 == height) { + avc_biwgt_4x4_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } else { + avc_biwgt_4x8_lasx(src, dst, stride, log2_denom, weight_src, + weight_dst, offset); + } +} + +void ff_weight_h264_pixels16_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset_in) +{ + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i zero = __lasx_xvldi(0); + __m256i src0, src1, src2, src3; + __m256i src0_l, src1_l, src2_l, src3_l, src0_h, src1_h, src2_h, src3_h; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i wgt, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, tmp4, + 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, offset, + src3_h, offset, src2_l, src2_h, src3_l, src3_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + __lasx_xvstelm_d(src0_l, src, 0, 0); + __lasx_xvstelm_d(src0_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src0_l, src, 0, 2); + __lasx_xvstelm_d(src0_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 0); + __lasx_xvstelm_d(src1_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 2); + __lasx_xvstelm_d(src1_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 0); + __lasx_xvstelm_d(src2_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 2); + __lasx_xvstelm_d(src2_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 0); + __lasx_xvstelm_d(src3_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 2); + __lasx_xvstelm_d(src3_h, src, 8, 2); + src += stride; + + if (16 == height) { + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG3(__lasx_xvpermi_q, tmp1, tmp0, 0x20, tmp3, tmp2, 0x20, tmp5, + tmp4, 0x20, tmp7, tmp6, 0x20, src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, + zero, src3, src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, + offset, src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, + offset, src3_h, offset, src2_l, src2_h, src3_l, src3_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + __lasx_xvstelm_d(src0_l, src, 0, 0); + __lasx_xvstelm_d(src0_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src0_l, src, 0, 2); + __lasx_xvstelm_d(src0_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 0); + __lasx_xvstelm_d(src1_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src1_l, src, 0, 2); + __lasx_xvstelm_d(src1_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 0); + __lasx_xvstelm_d(src2_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src2_l, src, 0, 2); + __lasx_xvstelm_d(src2_h, src, 8, 2); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 0); + __lasx_xvstelm_d(src3_h, src, 8, 0); + src += stride; + __lasx_xvstelm_d(src3_l, src, 0, 2); + __lasx_xvstelm_d(src3_h, src, 8, 2); + } +} + +static void avc_wgt_8x4_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + __m256i wgt, zero = __lasx_xvldi(0); + __m256i src0, src0_h, src0_l; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + src0_l = __lasx_xvilvl_b(zero, src0); + src0_h = __lasx_xvilvh_b(zero, src0); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src0_l = __lasx_xvsadd_h(src0_l, offset); + src0_h = __lasx_xvsadd_h(src0_h, offset); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + + src0 = __lasx_xvpickev_d(src0_h, src0_l); + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); +} + +static void avc_wgt_8x8_lasx(uint8_t *src, ptrdiff_t stride, int32_t log2_denom, + int32_t src_weight, int32_t offset_in) +{ + __m256i src0, src1, src0_h, src0_l, src1_h, src1_l, zero = __lasx_xvldi(0); + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset, wgt; + uint32_t offset_val; + uint8_t* src_tmp = src; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(src_weight); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP2_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, src0_l, src1_l); + DUP2_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, src0_h, src1_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + + DUP2_ARG2(__lasx_xvpickev_d, src0_h, src0_l, src1_h, src1_l, src0, src1); + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src1, src, 0, 0); + __lasx_xvstelm_d(src1, src + stride, 0, 1); + __lasx_xvstelm_d(src1, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src1, src + stride_3x, 0, 3); +} + +static void avc_wgt_8x16_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t src_weight, + int32_t offset_in) +{ + __m256i src0, src1, src2, src3; + __m256i src0_h, src0_l, src1_h, src1_l, src2_h, src2_l, src3_h, src3_l; + __m256i tmp0, tmp1, tmp2, tmp3, denom, offset, wgt; + __m256i zero = __lasx_xvldi(0); + uint32_t offset_val; + uint8_t* src_tmp = src; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(src_weight); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src1 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + src_tmp += stride_4x; + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src2 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + DUP4_ARG2(__lasx_xvldx, src_tmp, 0, src_tmp, stride, src_tmp, stride_2x, + src_tmp, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src3 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + + DUP4_ARG2(__lasx_xvilvl_b, zero, src0, zero, src1, zero, src2, zero, src3, + src0_l, src1_l, src2_l, src3_l); + DUP4_ARG2(__lasx_xvilvh_b, zero, src0, zero, src1, zero, src2, zero, src3, + src0_h, src1_h, src2_h, src3_h); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src1_l = __lasx_xvmul_h(wgt, src1_l); + src1_h = __lasx_xvmul_h(wgt, src1_h); + src2_l = __lasx_xvmul_h(wgt, src2_l); + src2_h = __lasx_xvmul_h(wgt, src2_h); + src3_l = __lasx_xvmul_h(wgt, src3_l); + src3_h = __lasx_xvmul_h(wgt, src3_h); + + DUP4_ARG2(__lasx_xvsadd_h, src0_l, offset, src0_h, offset, src1_l, offset, + src1_h, offset, src0_l, src0_h, src1_l, src1_h); + DUP4_ARG2(__lasx_xvsadd_h, src2_l, offset, src2_h, offset, src3_l, offset, + src3_h, offset, src2_l, src2_h, src3_l, src3_h); + + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src1_l = __lasx_xvmaxi_h(src1_l, 0); + src1_h = __lasx_xvmaxi_h(src1_h, 0); + src2_l = __lasx_xvmaxi_h(src2_l, 0); + src2_h = __lasx_xvmaxi_h(src2_h, 0); + src3_l = __lasx_xvmaxi_h(src3_l, 0); + src3_h = __lasx_xvmaxi_h(src3_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + src1_l = __lasx_xvssrlrn_bu_h(src1_l, denom); + src1_h = __lasx_xvssrlrn_bu_h(src1_h, denom); + src2_l = __lasx_xvssrlrn_bu_h(src2_l, denom); + src2_h = __lasx_xvssrlrn_bu_h(src2_h, denom); + src3_l = __lasx_xvssrlrn_bu_h(src3_l, denom); + src3_h = __lasx_xvssrlrn_bu_h(src3_h, denom); + DUP4_ARG2(__lasx_xvpickev_d, src0_h, src0_l, src1_h, src1_l, src2_h, src2_l, + src3_h, src3_l, src0, src1, src2, src3); + + __lasx_xvstelm_d(src0, src, 0, 0); + __lasx_xvstelm_d(src0, src + stride, 0, 1); + __lasx_xvstelm_d(src0, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src0, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src1, src, 0, 0); + __lasx_xvstelm_d(src1, src + stride, 0, 1); + __lasx_xvstelm_d(src1, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src1, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src2, src, 0, 0); + __lasx_xvstelm_d(src2, src + stride, 0, 1); + __lasx_xvstelm_d(src2, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src2, src + stride_3x, 0, 3); + src += stride_4x; + __lasx_xvstelm_d(src3, src, 0, 0); + __lasx_xvstelm_d(src3, src + stride, 0, 1); + __lasx_xvstelm_d(src3, src + stride_2x, 0, 2); + __lasx_xvstelm_d(src3, src + stride_3x, 0, 3); +} + +void ff_weight_h264_pixels8_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset) +{ + if (4 == height) { + avc_wgt_8x4_lasx(src, stride, log2_denom, weight_src, offset); + } else if (8 == height) { + avc_wgt_8x8_lasx(src, stride, log2_denom, weight_src, offset); + } else { + avc_wgt_8x16_lasx(src, stride, log2_denom, weight_src, offset); + } +} + +static void avc_wgt_4x2_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + uint32_t offset_val; + __m256i wgt, zero = __lasx_xvldi(0); + __m256i src0, tmp0, tmp1, denom, offset; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP2_ARG2(__lasx_xvldx, src, 0, src, stride, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + src0 = __lasx_xvilvl_b(zero, src0); + src0 = __lasx_xvmul_h(wgt, src0); + src0 = __lasx_xvsadd_h(src0, offset); + src0 = __lasx_xvmaxi_h(src0, 0); + src0 = __lasx_xvssrlrn_bu_h(src0, denom); + __lasx_xvstelm_w(src0, src, 0, 0); + __lasx_xvstelm_w(src0, src + stride, 0, 1); +} + +static void avc_wgt_4x4_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + __m256i wgt; + __m256i src0, tmp0, tmp1, tmp2, tmp3, denom, offset; + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp0, tmp1); + src0 = __lasx_xvilvl_w(tmp1, tmp0); + src0 = __lasx_vext2xv_hu_bu(src0); + src0 = __lasx_xvmul_h(wgt, src0); + src0 = __lasx_xvsadd_h(src0, offset); + src0 = __lasx_xvmaxi_h(src0, 0); + src0 = __lasx_xvssrlrn_bu_h(src0, denom); + __lasx_xvstelm_w(src0, src, 0, 0); + __lasx_xvstelm_w(src0, src + stride, 0, 1); + __lasx_xvstelm_w(src0, src + stride_2x, 0, 4); + __lasx_xvstelm_w(src0, src + stride_3x, 0, 5); +} + +static void avc_wgt_4x8_lasx(uint8_t *src, ptrdiff_t stride, + int32_t log2_denom, int32_t weight_src, + int32_t offset_in) +{ + __m256i src0, src0_h, src0_l; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, denom, offset; + __m256i wgt, zero = __lasx_xvldi(0); + uint32_t offset_val; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_4x = stride << 2; + ptrdiff_t stride_3x = stride_2x + stride; + + offset_val = (unsigned) offset_in << log2_denom; + + wgt = __lasx_xvreplgr2vr_h(weight_src); + offset = __lasx_xvreplgr2vr_h(offset_val); + denom = __lasx_xvreplgr2vr_h(log2_denom); + + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp0, tmp1, tmp2, tmp3); + src += stride_4x; + DUP4_ARG2(__lasx_xvldx, src, 0, src, stride, src, stride_2x, + src, stride_3x, tmp4, tmp5, tmp6, tmp7); + src -= stride_4x; + DUP4_ARG2(__lasx_xvilvl_w, tmp2, tmp0, tmp3, tmp1, tmp6, tmp4, tmp7, + tmp5, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lasx_xvilvl_w, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + src0 = __lasx_xvpermi_q(tmp1, tmp0, 0x20); + src0_l = __lasx_xvilvl_b(zero, src0); + src0_h = __lasx_xvilvh_b(zero, src0); + src0_l = __lasx_xvmul_h(wgt, src0_l); + src0_h = __lasx_xvmul_h(wgt, src0_h); + src0_l = __lasx_xvsadd_h(src0_l, offset); + src0_h = __lasx_xvsadd_h(src0_h, offset); + src0_l = __lasx_xvmaxi_h(src0_l, 0); + src0_h = __lasx_xvmaxi_h(src0_h, 0); + src0_l = __lasx_xvssrlrn_bu_h(src0_l, denom); + src0_h = __lasx_xvssrlrn_bu_h(src0_h, denom); + __lasx_xvstelm_w(src0_l, src, 0, 0); + __lasx_xvstelm_w(src0_l, src + stride, 0, 1); + __lasx_xvstelm_w(src0_h, src + stride_2x, 0, 0); + __lasx_xvstelm_w(src0_h, src + stride_3x, 0, 1); + src += stride_4x; + __lasx_xvstelm_w(src0_l, src, 0, 4); + __lasx_xvstelm_w(src0_l, src + stride, 0, 5); + __lasx_xvstelm_w(src0_h, src + stride_2x, 0, 4); + __lasx_xvstelm_w(src0_h, src + stride_3x, 0, 5); +} + +void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset) +{ + if (2 == height) { + avc_wgt_4x2_lasx(src, stride, log2_denom, weight_src, offset); + } else if (4 == height) { + avc_wgt_4x4_lasx(src, stride, log2_denom, weight_src, offset); + } else { + avc_wgt_4x8_lasx(src, stride, log2_denom, weight_src, offset); + } +} + +void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride) +{ + __m256i src0, dst0, dst1, dst2, dst3, zero; + __m256i tmp0, tmp1; + uint8_t* _dst1 = _dst + stride; + uint8_t* _dst2 = _dst1 + stride; + uint8_t* _dst3 = _dst2 + stride; + + src0 = __lasx_xvld(_src, 0); + dst0 = __lasx_xvldrepl_w(_dst, 0); + dst1 = __lasx_xvldrepl_w(_dst1, 0); + dst2 = __lasx_xvldrepl_w(_dst2, 0); + dst3 = __lasx_xvldrepl_w(_dst3, 0); + tmp0 = __lasx_xvilvl_w(dst1, dst0); + tmp1 = __lasx_xvilvl_w(dst3, dst2); + dst0 = __lasx_xvilvl_d(tmp1, tmp0); + tmp0 = __lasx_vext2xv_hu_bu(dst0); + zero = __lasx_xvldi(0); + tmp1 = __lasx_xvadd_h(src0, tmp0); + dst0 = __lasx_xvpickev_b(tmp1, tmp1); + __lasx_xvstelm_w(dst0, _dst, 0, 0); + __lasx_xvstelm_w(dst0, _dst1, 0, 1); + __lasx_xvstelm_w(dst0, _dst2, 0, 4); + __lasx_xvstelm_w(dst0, _dst3, 0, 5); + __lasx_xvst(zero, _src, 0); +} + +void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride) +{ + __m256i src0, src1, src2, src3; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i zero = __lasx_xvldi(0); + uint8_t *_dst1 = _dst + stride; + uint8_t *_dst2 = _dst1 + stride; + uint8_t *_dst3 = _dst2 + stride; + uint8_t *_dst4 = _dst3 + stride; + uint8_t *_dst5 = _dst4 + stride; + uint8_t *_dst6 = _dst5 + stride; + uint8_t *_dst7 = _dst6 + stride; + + src0 = __lasx_xvld(_src, 0); + src1 = __lasx_xvld(_src, 32); + src2 = __lasx_xvld(_src, 64); + src3 = __lasx_xvld(_src, 96); + dst0 = __lasx_xvldrepl_d(_dst, 0); + dst1 = __lasx_xvldrepl_d(_dst1, 0); + dst2 = __lasx_xvldrepl_d(_dst2, 0); + dst3 = __lasx_xvldrepl_d(_dst3, 0); + dst4 = __lasx_xvldrepl_d(_dst4, 0); + dst5 = __lasx_xvldrepl_d(_dst5, 0); + dst6 = __lasx_xvldrepl_d(_dst6, 0); + dst7 = __lasx_xvldrepl_d(_dst7, 0); + tmp0 = __lasx_xvilvl_d(dst1, dst0); + tmp1 = __lasx_xvilvl_d(dst3, dst2); + tmp2 = __lasx_xvilvl_d(dst5, dst4); + tmp3 = __lasx_xvilvl_d(dst7, dst6); + dst0 = __lasx_vext2xv_hu_bu(tmp0); + dst1 = __lasx_vext2xv_hu_bu(tmp1); + dst1 = __lasx_vext2xv_hu_bu(tmp1); + dst2 = __lasx_vext2xv_hu_bu(tmp2); + dst3 = __lasx_vext2xv_hu_bu(tmp3); + tmp0 = __lasx_xvadd_h(src0, dst0); + tmp1 = __lasx_xvadd_h(src1, dst1); + tmp2 = __lasx_xvadd_h(src2, dst2); + tmp3 = __lasx_xvadd_h(src3, dst3); + dst1 = __lasx_xvpickev_b(tmp1, tmp0); + dst2 = __lasx_xvpickev_b(tmp3, tmp2); + __lasx_xvst(zero, _src, 0); + __lasx_xvst(zero, _src, 32); + __lasx_xvst(zero, _src, 64); + __lasx_xvst(zero, _src, 96); + __lasx_xvstelm_d(dst1, _dst, 0, 0); + __lasx_xvstelm_d(dst1, _dst1, 0, 2); + __lasx_xvstelm_d(dst1, _dst2, 0, 1); + __lasx_xvstelm_d(dst1, _dst3, 0, 3); + __lasx_xvstelm_d(dst2, _dst4, 0, 0); + __lasx_xvstelm_d(dst2, _dst5, 0, 2); + __lasx_xvstelm_d(dst2, _dst6, 0, 1); + __lasx_xvstelm_d(dst2, _dst7, 0, 3); +} diff --git a/libavcodec/loongarch/h264dsp_lasx.h b/libavcodec/loongarch/h264dsp_lasx.h new file mode 100644 index 0000000000..4cf813750b --- /dev/null +++ b/libavcodec/loongarch/h264dsp_lasx.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * 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 + */ + +#ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H +#define AVCODEC_LOONGARCH_H264DSP_LASX_H + +#include "libavcodec/h264dec.h" + +void ff_h264_h_lpf_luma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_luma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_luma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_luma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_h_lpf_chroma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_chroma_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_h_lpf_chroma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_h264_v_lpf_chroma_intra_8_lasx(uint8_t *src, ptrdiff_t stride, + int alpha, int beta); +void ff_biweight_h264_pixels16_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset_in); +void ff_biweight_h264_pixels8_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset); +void ff_biweight_h264_pixels4_8_lasx(uint8_t *dst, uint8_t *src, + ptrdiff_t stride, int height, + int log2_denom, int weight_dst, + int weight_src, int offset); +void ff_weight_h264_pixels16_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset_in); +void ff_weight_h264_pixels8_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_weight_h264_pixels4_8_lasx(uint8_t *src, ptrdiff_t stride, + int height, int log2_denom, + int weight_src, int offset); +void ff_h264_add_pixels4_8_lasx(uint8_t *_dst, int16_t *_src, int stride); + +void ff_h264_add_pixels8_8_lasx(uint8_t *_dst, int16_t *_src, int stride); +void ff_h264_idct_add_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride); +void ff_h264_idct8_addblk_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride); +void ff_h264_idct4x4_addblk_dc_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride); +void ff_h264_idct8_dc_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride); +void ff_h264_idct_add16_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct8_add4_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add8_lasx(uint8_t **dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add8_422_lasx(uint8_t **dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_idct_add16_intra_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]); +void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, + int32_t de_qval); + +void ff_h264_loop_filter_strength_lasx(int16_t bS[2][4][4], uint8_t nnz[40], + int8_t ref[2][40], int16_t mv[2][40][2], + int bidir, int edges, int step, + int mask_mv0, int mask_mv1, int field); + +#endif // #ifndef AVCODEC_LOONGARCH_H264DSP_LASX_H diff --git a/libavcodec/loongarch/h264idct_lasx.c b/libavcodec/loongarch/h264idct_lasx.c new file mode 100644 index 0000000000..46bd3b74d5 --- /dev/null +++ b/libavcodec/loongarch/h264idct_lasx.c @@ -0,0 +1,498 @@ +/* + * Loongson LASX optimized h264dsp + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Shiyou Yin + * 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 "libavutil/loongarch/loongson_intrinsics.h" +#include "h264dsp_lasx.h" +#include "libavcodec/bit_depth_template.c" + +#define AVC_ITRANS_H(in0, in1, in2, in3, out0, out1, out2, out3) \ +{ \ + __m256i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + \ + tmp0_m = __lasx_xvadd_h(in0, in2); \ + tmp1_m = __lasx_xvsub_h(in0, in2); \ + tmp2_m = __lasx_xvsrai_h(in1, 1); \ + tmp2_m = __lasx_xvsub_h(tmp2_m, in3); \ + tmp3_m = __lasx_xvsrai_h(in3, 1); \ + tmp3_m = __lasx_xvadd_h(in1, tmp3_m); \ + \ + LASX_BUTTERFLY_4_H(tmp0_m, tmp1_m, tmp2_m, tmp3_m, \ + out0, out1, out2, out3); \ +} + +void ff_h264_idct_add_lasx(uint8_t *dst, int16_t *src, int32_t dst_stride) +{ + __m256i src0_m, src1_m, src2_m, src3_m; + __m256i dst0_m, dst1_m; + __m256i hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3; + __m256i inp0_m, inp1_m, res0_m, src1, src3; + __m256i src0 = __lasx_xvld(src, 0); + __m256i src2 = __lasx_xvld(src, 16); + __m256i zero = __lasx_xvldi(0); + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + + __lasx_xvst(zero, src, 0); + DUP2_ARG2(__lasx_xvilvh_d, src0, src0, src2, src2, src1, src3); + AVC_ITRANS_H(src0, src1, src2, src3, hres0, hres1, hres2, hres3); + LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, hres0, hres1, hres2, hres3); + AVC_ITRANS_H(hres0, hres1, hres2, hres3, vres0, vres1, vres2, vres3); + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, src0_m, src1_m, src2_m, src3_m); + DUP4_ARG2(__lasx_xvld, dst, 0, dst + dst_stride, 0, dst + dst_stride_2x, + 0, dst + dst_stride_3x, 0, src0_m, src1_m, src2_m, src3_m); + DUP2_ARG2(__lasx_xvilvl_d, vres1, vres0, vres3, vres2, inp0_m, inp1_m); + inp0_m = __lasx_xvpermi_q(inp1_m, inp0_m, 0x20); + inp0_m = __lasx_xvsrari_h(inp0_m, 6); + DUP2_ARG2(__lasx_xvilvl_w, src1_m, src0_m, src3_m, src2_m, dst0_m, dst1_m); + dst0_m = __lasx_xvilvl_d(dst1_m, dst0_m); + res0_m = __lasx_vext2xv_hu_bu(dst0_m); + res0_m = __lasx_xvadd_h(res0_m, inp0_m); + res0_m = __lasx_xvclip255_h(res0_m); + dst0_m = __lasx_xvpickev_b(res0_m, res0_m); + __lasx_xvstelm_w(dst0_m, dst, 0, 0); + __lasx_xvstelm_w(dst0_m, dst + dst_stride, 0, 1); + __lasx_xvstelm_w(dst0_m, dst + dst_stride_2x, 0, 4); + __lasx_xvstelm_w(dst0_m, dst + dst_stride_3x, 0, 5); +} + +void ff_h264_idct8_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + __m256i src0, src1, src2, src3, src4, src5, src6, src7; + __m256i vec0, vec1, vec2, vec3; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m256i res0, res1, res2, res3, res4, res5, res6, res7; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i zero = __lasx_xvldi(0); + 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; + + src[0] += 32; + DUP4_ARG2(__lasx_xvld, src, 0, src, 16, src, 32, src, 48, + src0, src1, src2, src3); + DUP4_ARG2(__lasx_xvld, src, 64, src, 80, src, 96, src, 112, + src4, src5, src6, src7); + __lasx_xvst(zero, src, 0); + __lasx_xvst(zero, src, 32); + __lasx_xvst(zero, src, 64); + __lasx_xvst(zero, src, 96); + + vec0 = __lasx_xvadd_h(src0, src4); + vec1 = __lasx_xvsub_h(src0, src4); + vec2 = __lasx_xvsrai_h(src2, 1); + vec2 = __lasx_xvsub_h(vec2, src6); + vec3 = __lasx_xvsrai_h(src6, 1); + vec3 = __lasx_xvadd_h(src2, vec3); + + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, tmp0, tmp1, tmp2, tmp3); + + vec0 = __lasx_xvsrai_h(src7, 1); + vec0 = __lasx_xvsub_h(src5, vec0); + vec0 = __lasx_xvsub_h(vec0, src3); + vec0 = __lasx_xvsub_h(vec0, src7); + + vec1 = __lasx_xvsrai_h(src3, 1); + vec1 = __lasx_xvsub_h(src1, vec1); + vec1 = __lasx_xvadd_h(vec1, src7); + vec1 = __lasx_xvsub_h(vec1, src3); + + vec2 = __lasx_xvsrai_h(src5, 1); + vec2 = __lasx_xvsub_h(vec2, src1); + vec2 = __lasx_xvadd_h(vec2, src7); + vec2 = __lasx_xvadd_h(vec2, src5); + + vec3 = __lasx_xvsrai_h(src1, 1); + vec3 = __lasx_xvadd_h(src3, vec3); + vec3 = __lasx_xvadd_h(vec3, src5); + vec3 = __lasx_xvadd_h(vec3, src1); + + tmp4 = __lasx_xvsrai_h(vec3, 2); + tmp4 = __lasx_xvadd_h(tmp4, vec0); + tmp5 = __lasx_xvsrai_h(vec2, 2); + tmp5 = __lasx_xvadd_h(tmp5, vec1); + tmp6 = __lasx_xvsrai_h(vec1, 2); + tmp6 = __lasx_xvsub_h(tmp6, vec2); + tmp7 = __lasx_xvsrai_h(vec0, 2); + tmp7 = __lasx_xvsub_h(vec3, tmp7); + + LASX_BUTTERFLY_8_H(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, + res0, res1, res2, res3, res4, res5, res6, res7); + LASX_TRANSPOSE8x8_H(res0, res1, res2, res3, res4, res5, res6, res7, + res0, res1, res2, res3, res4, res5, res6, res7); + + DUP4_ARG1(__lasx_vext2xv_w_h, res0, res1, res2, res3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG1(__lasx_vext2xv_w_h, res4, res5, res6, res7, + tmp4, tmp5, tmp6, tmp7); + vec0 = __lasx_xvadd_w(tmp0, tmp4); + vec1 = __lasx_xvsub_w(tmp0, tmp4); + + vec2 = __lasx_xvsrai_w(tmp2, 1); + vec2 = __lasx_xvsub_w(vec2, tmp6); + vec3 = __lasx_xvsrai_w(tmp6, 1); + vec3 = __lasx_xvadd_w(vec3, tmp2); + + tmp0 = __lasx_xvadd_w(vec0, vec3); + tmp2 = __lasx_xvadd_w(vec1, vec2); + tmp4 = __lasx_xvsub_w(vec1, vec2); + tmp6 = __lasx_xvsub_w(vec0, vec3); + + vec0 = __lasx_xvsrai_w(tmp7, 1); + vec0 = __lasx_xvsub_w(tmp5, vec0); + vec0 = __lasx_xvsub_w(vec0, tmp3); + vec0 = __lasx_xvsub_w(vec0, tmp7); + + vec1 = __lasx_xvsrai_w(tmp3, 1); + vec1 = __lasx_xvsub_w(tmp1, vec1); + vec1 = __lasx_xvadd_w(vec1, tmp7); + vec1 = __lasx_xvsub_w(vec1, tmp3); + + vec2 = __lasx_xvsrai_w(tmp5, 1); + vec2 = __lasx_xvsub_w(vec2, tmp1); + vec2 = __lasx_xvadd_w(vec2, tmp7); + vec2 = __lasx_xvadd_w(vec2, tmp5); + + vec3 = __lasx_xvsrai_w(tmp1, 1); + vec3 = __lasx_xvadd_w(tmp3, vec3); + vec3 = __lasx_xvadd_w(vec3, tmp5); + vec3 = __lasx_xvadd_w(vec3, tmp1); + + tmp1 = __lasx_xvsrai_w(vec3, 2); + tmp1 = __lasx_xvadd_w(tmp1, vec0); + tmp3 = __lasx_xvsrai_w(vec2, 2); + tmp3 = __lasx_xvadd_w(tmp3, vec1); + tmp5 = __lasx_xvsrai_w(vec1, 2); + tmp5 = __lasx_xvsub_w(tmp5, vec2); + tmp7 = __lasx_xvsrai_w(vec0, 2); + tmp7 = __lasx_xvsub_w(vec3, tmp7); + + LASX_BUTTERFLY_4_W(tmp0, tmp2, tmp5, tmp7, res0, res1, res6, res7); + LASX_BUTTERFLY_4_W(tmp4, tmp6, tmp1, tmp3, res2, res3, res4, res5); + + DUP4_ARG2(__lasx_xvsrai_w, res0, 6, res1, 6, res2, 6, res3, 6, + res0, res1, res2, res3); + DUP4_ARG2(__lasx_xvsrai_w, res4, 6, res5, 6, res6, 6, res7, 6, + res4, res5, res6, res7); + DUP4_ARG2(__lasx_xvpickev_h, res1, res0, res3, res2, res5, res4, res7, + res6, res0, res1, res2, res3); + DUP4_ARG2(__lasx_xvpermi_d, res0, 0xd8, res1, 0xd8, res2, 0xd8, res3, 0xd8, + res0, res1, res2, res3); + + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst0, dst1, dst2, dst3); + dst += dst_stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst4, dst5, dst6, dst7); + dst -= dst_stride_4x; + DUP4_ARG2(__lasx_xvilvl_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lasx_xvilvl_b, zero, dst4, zero, dst5, zero, dst6, zero, dst7, + dst4, dst5, dst6, dst7); + DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, + dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); + res0 = __lasx_xvadd_h(res0, dst0); + res1 = __lasx_xvadd_h(res1, dst1); + res2 = __lasx_xvadd_h(res2, dst2); + res3 = __lasx_xvadd_h(res3, dst3); + DUP4_ARG1(__lasx_xvclip255_h, res0, res1, res2, res3, res0, res1, + res2, res3); + DUP2_ARG2(__lasx_xvpickev_b, res1, res0, res3, res2, res0, res1); + __lasx_xvstelm_d(res0, dst, 0, 0); + __lasx_xvstelm_d(res0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(res0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(res0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(res1, dst, 0, 0); + __lasx_xvstelm_d(res1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(res1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(res1, dst + dst_stride_3x, 0, 3); +} + +void ff_h264_idct4x4_addblk_dc_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + const int16_t dc = (src[0] + 32) >> 6; + int32_t dst_stride_2x = dst_stride << 1; + int32_t dst_stride_3x = dst_stride_2x + dst_stride; + __m256i pred, out; + __m256i src0, src1, src2, src3; + __m256i input_dc = __lasx_xvreplgr2vr_h(dc); + + src[0] = 0; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, src0, src1, src2, src3); + DUP2_ARG2(__lasx_xvilvl_w, src1, src0, src3, src2, src0, src1); + + pred = __lasx_xvpermi_q(src0, src1, 0x02); + pred = __lasx_xvaddw_h_h_bu(input_dc, pred); + pred = __lasx_xvclip255_h(pred); + out = __lasx_xvpickev_b(pred, pred); + __lasx_xvstelm_w(out, dst, 0, 0); + __lasx_xvstelm_w(out, dst + dst_stride, 0, 1); + __lasx_xvstelm_w(out, dst + dst_stride_2x, 0, 4); + __lasx_xvstelm_w(out, dst + dst_stride_3x, 0, 5); +} + +void ff_h264_idct8_dc_addblk_lasx(uint8_t *dst, int16_t *src, + int32_t dst_stride) +{ + int32_t dc_val; + 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; + __m256i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m256i dc; + + dc_val = (src[0] + 32) >> 6; + dc = __lasx_xvreplgr2vr_h(dc_val); + + src[0] = 0; + + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst0, dst1, dst2, dst3); + dst += dst_stride_4x; + DUP4_ARG2(__lasx_xvldx, dst, 0, dst, dst_stride, dst, dst_stride_2x, + dst, dst_stride_3x, dst4, dst5, dst6, dst7); + dst -= dst_stride_4x; + DUP4_ARG1(__lasx_vext2xv_hu_bu, dst0, dst1, dst2, dst3, + dst0, dst1, dst2, dst3); + DUP4_ARG1(__lasx_vext2xv_hu_bu, dst4, dst5, dst6, dst7, + dst4, dst5, dst6, dst7); + DUP4_ARG3(__lasx_xvpermi_q, dst1, dst0, 0x20, dst3, dst2, 0x20, dst5, + dst4, 0x20, dst7, dst6, 0x20, dst0, dst1, dst2, dst3); + dst0 = __lasx_xvadd_h(dst0, dc); + dst1 = __lasx_xvadd_h(dst1, dc); + dst2 = __lasx_xvadd_h(dst2, dc); + dst3 = __lasx_xvadd_h(dst3, dc); + DUP4_ARG1(__lasx_xvclip255_h, dst0, dst1, dst2, dst3, + dst0, dst1, dst2, dst3); + DUP2_ARG2(__lasx_xvpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(dst0, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(dst0, dst + dst_stride_3x, 0, 3); + dst += dst_stride_4x; + __lasx_xvstelm_d(dst1, dst, 0, 0); + __lasx_xvstelm_d(dst1, dst + dst_stride, 0, 2); + __lasx_xvstelm_d(dst1, dst + dst_stride_2x, 0, 1); + __lasx_xvstelm_d(dst1, dst + dst_stride_3x, 0, 3); +} + +void ff_h264_idct_add16_lasx(uint8_t *dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 0; i < 16; i++) { + int32_t nnz = nzc[scan8[i]]; + + if (nnz) { + if (nnz == 1 && ((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else + ff_h264_idct_add_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + } +} + +void ff_h264_idct8_add4_lasx(uint8_t *dst, const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t cnt; + + for (cnt = 0; cnt < 16; cnt += 4) { + int32_t nnz = nzc[scan8[cnt]]; + + if (nnz) { + if (nnz == 1 && ((dctcoef *) block)[cnt * 16]) + ff_h264_idct8_dc_addblk_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + else + ff_h264_idct8_addblk_lasx(dst + blk_offset[cnt], + block + cnt * 16 * sizeof(pixel), + dst_stride); + } + } +} + + +void ff_h264_idct_add8_lasx(uint8_t **dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 16; i < 20; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 32; i < 36; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add8_422_lasx(uint8_t **dst, + const int32_t *blk_offset, + int16_t *block, int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 16; i < 20; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 32; i < 36; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 20; i < 24; i++) { + if (nzc[scan8[i + 4]]) + ff_h264_idct_add_lasx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[0] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } + for (i = 36; i < 40; i++) { + if (nzc[scan8[i + 4]]) + ff_h264_idct_add_lasx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst[1] + blk_offset[i + 4], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_idct_add16_intra_lasx(uint8_t *dst, + const int32_t *blk_offset, + int16_t *block, + int32_t dst_stride, + const uint8_t nzc[15 * 8]) +{ + int32_t i; + + for (i = 0; i < 16; i++) { + if (nzc[scan8[i]]) + ff_h264_idct_add_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), dst_stride); + else if (((dctcoef *) block)[i * 16]) + ff_h264_idct4x4_addblk_dc_lasx(dst + blk_offset[i], + block + i * 16 * sizeof(pixel), + dst_stride); + } +} + +void ff_h264_deq_idct_luma_dc_lasx(int16_t *dst, int16_t *src, + int32_t de_qval) +{ +#define DC_DEST_STRIDE 16 + + __m256i src0, src1, src2, src3; + __m256i vec0, vec1, vec2, vec3; + __m256i tmp0, tmp1, tmp2, tmp3; + __m256i hres0, hres1, hres2, hres3; + __m256i vres0, vres1, vres2, vres3; + __m256i de_q_vec = __lasx_xvreplgr2vr_w(de_qval); + + DUP4_ARG2(__lasx_xvld, src, 0, src, 8, src, 16, src, 24, + src0, src1, src2, src3); + LASX_TRANSPOSE4x4_H(src0, src1, src2, src3, tmp0, tmp1, tmp2, tmp3); + LASX_BUTTERFLY_4_H(tmp0, tmp2, tmp3, tmp1, vec0, vec3, vec2, vec1); + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, hres0, hres3, hres2, hres1); + LASX_TRANSPOSE4x4_H(hres0, hres1, hres2, hres3, + hres0, hres1, hres2, hres3); + LASX_BUTTERFLY_4_H(hres0, hres1, hres3, hres2, vec0, vec3, vec2, vec1); + LASX_BUTTERFLY_4_H(vec0, vec1, vec2, vec3, vres0, vres1, vres2, vres3); + DUP4_ARG1(__lasx_vext2xv_w_h, vres0, vres1, vres2, vres3, + vres0, vres1, vres2, vres3); + DUP2_ARG3(__lasx_xvpermi_q, vres1, vres0, 0x20, vres3, vres2, 0x20, + vres0, vres1); + + vres0 = __lasx_xvmul_w(vres0, de_q_vec); + vres1 = __lasx_xvmul_w(vres1, de_q_vec); + + vres0 = __lasx_xvsrari_w(vres0, 8); + vres1 = __lasx_xvsrari_w(vres1, 8); + vec0 = __lasx_xvpickev_h(vres1, vres0); + vec0 = __lasx_xvpermi_d(vec0, 0xd8); + __lasx_xvstelm_h(vec0, dst + 0 * DC_DEST_STRIDE, 0, 0); + __lasx_xvstelm_h(vec0, dst + 2 * DC_DEST_STRIDE, 0, 1); + __lasx_xvstelm_h(vec0, dst + 8 * DC_DEST_STRIDE, 0, 2); + __lasx_xvstelm_h(vec0, dst + 10 * DC_DEST_STRIDE, 0, 3); + __lasx_xvstelm_h(vec0, dst + 1 * DC_DEST_STRIDE, 0, 4); + __lasx_xvstelm_h(vec0, dst + 3 * DC_DEST_STRIDE, 0, 5); + __lasx_xvstelm_h(vec0, dst + 9 * DC_DEST_STRIDE, 0, 6); + __lasx_xvstelm_h(vec0, dst + 11 * DC_DEST_STRIDE, 0, 7); + __lasx_xvstelm_h(vec0, dst + 4 * DC_DEST_STRIDE, 0, 8); + __lasx_xvstelm_h(vec0, dst + 6 * DC_DEST_STRIDE, 0, 9); + __lasx_xvstelm_h(vec0, dst + 12 * DC_DEST_STRIDE, 0, 10); + __lasx_xvstelm_h(vec0, dst + 14 * DC_DEST_STRIDE, 0, 11); + __lasx_xvstelm_h(vec0, dst + 5 * DC_DEST_STRIDE, 0, 12); + __lasx_xvstelm_h(vec0, dst + 7 * DC_DEST_STRIDE, 0, 13); + __lasx_xvstelm_h(vec0, dst + 13 * DC_DEST_STRIDE, 0, 14); + __lasx_xvstelm_h(vec0, dst + 15 * DC_DEST_STRIDE, 0, 15); + +#undef DC_DEST_STRIDE +} diff --git a/libavcodec/loongarch/h264qpel_init_loongarch.c b/libavcodec/loongarch/h264qpel_init_loongarch.c new file mode 100644 index 0000000000..969c9c376c --- /dev/null +++ b/libavcodec/loongarch/h264qpel_init_loongarch.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 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 "h264qpel_lasx.h" +#include "libavutil/attributes.h" +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/h264qpel.h" + +av_cold void ff_h264qpel_init_loongarch(H264QpelContext *c, int bit_depth) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lasx(cpu_flags)) { + if (8 == bit_depth) { + c->put_h264_qpel_pixels_tab[0][0] = ff_put_h264_qpel16_mc00_lasx; + c->put_h264_qpel_pixels_tab[0][1] = ff_put_h264_qpel16_mc10_lasx; + c->put_h264_qpel_pixels_tab[0][2] = ff_put_h264_qpel16_mc20_lasx; + c->put_h264_qpel_pixels_tab[0][3] = ff_put_h264_qpel16_mc30_lasx; + c->put_h264_qpel_pixels_tab[0][4] = ff_put_h264_qpel16_mc01_lasx; + c->put_h264_qpel_pixels_tab[0][5] = ff_put_h264_qpel16_mc11_lasx; + + c->put_h264_qpel_pixels_tab[0][6] = ff_put_h264_qpel16_mc21_lasx; + c->put_h264_qpel_pixels_tab[0][7] = ff_put_h264_qpel16_mc31_lasx; + c->put_h264_qpel_pixels_tab[0][8] = ff_put_h264_qpel16_mc02_lasx; + c->put_h264_qpel_pixels_tab[0][9] = ff_put_h264_qpel16_mc12_lasx; + c->put_h264_qpel_pixels_tab[0][10] = ff_put_h264_qpel16_mc22_lasx; + c->put_h264_qpel_pixels_tab[0][11] = ff_put_h264_qpel16_mc32_lasx; + c->put_h264_qpel_pixels_tab[0][12] = ff_put_h264_qpel16_mc03_lasx; + c->put_h264_qpel_pixels_tab[0][13] = ff_put_h264_qpel16_mc13_lasx; + c->put_h264_qpel_pixels_tab[0][14] = ff_put_h264_qpel16_mc23_lasx; + c->put_h264_qpel_pixels_tab[0][15] = ff_put_h264_qpel16_mc33_lasx; + c->avg_h264_qpel_pixels_tab[0][0] = ff_avg_h264_qpel16_mc00_lasx; + c->avg_h264_qpel_pixels_tab[0][1] = ff_avg_h264_qpel16_mc10_lasx; + c->avg_h264_qpel_pixels_tab[0][2] = ff_avg_h264_qpel16_mc20_lasx; + c->avg_h264_qpel_pixels_tab[0][3] = ff_avg_h264_qpel16_mc30_lasx; + c->avg_h264_qpel_pixels_tab[0][4] = ff_avg_h264_qpel16_mc01_lasx; + c->avg_h264_qpel_pixels_tab[0][5] = ff_avg_h264_qpel16_mc11_lasx; + c->avg_h264_qpel_pixels_tab[0][6] = ff_avg_h264_qpel16_mc21_lasx; + c->avg_h264_qpel_pixels_tab[0][7] = ff_avg_h264_qpel16_mc31_lasx; + c->avg_h264_qpel_pixels_tab[0][8] = ff_avg_h264_qpel16_mc02_lasx; + c->avg_h264_qpel_pixels_tab[0][9] = ff_avg_h264_qpel16_mc12_lasx; + c->avg_h264_qpel_pixels_tab[0][10] = ff_avg_h264_qpel16_mc22_lasx; + c->avg_h264_qpel_pixels_tab[0][11] = ff_avg_h264_qpel16_mc32_lasx; + c->avg_h264_qpel_pixels_tab[0][12] = ff_avg_h264_qpel16_mc03_lasx; + c->avg_h264_qpel_pixels_tab[0][13] = ff_avg_h264_qpel16_mc13_lasx; + c->avg_h264_qpel_pixels_tab[0][14] = ff_avg_h264_qpel16_mc23_lasx; + c->avg_h264_qpel_pixels_tab[0][15] = ff_avg_h264_qpel16_mc33_lasx; + + c->put_h264_qpel_pixels_tab[1][0] = ff_put_h264_qpel8_mc00_lasx; + c->put_h264_qpel_pixels_tab[1][1] = ff_put_h264_qpel8_mc10_lasx; + c->put_h264_qpel_pixels_tab[1][2] = ff_put_h264_qpel8_mc20_lasx; + c->put_h264_qpel_pixels_tab[1][3] = ff_put_h264_qpel8_mc30_lasx; + c->put_h264_qpel_pixels_tab[1][4] = ff_put_h264_qpel8_mc01_lasx; + c->put_h264_qpel_pixels_tab[1][5] = ff_put_h264_qpel8_mc11_lasx; + c->put_h264_qpel_pixels_tab[1][6] = ff_put_h264_qpel8_mc21_lasx; + c->put_h264_qpel_pixels_tab[1][7] = ff_put_h264_qpel8_mc31_lasx; + c->put_h264_qpel_pixels_tab[1][8] = ff_put_h264_qpel8_mc02_lasx; + c->put_h264_qpel_pixels_tab[1][9] = ff_put_h264_qpel8_mc12_lasx; + c->put_h264_qpel_pixels_tab[1][10] = ff_put_h264_qpel8_mc22_lasx; + c->put_h264_qpel_pixels_tab[1][11] = ff_put_h264_qpel8_mc32_lasx; + c->put_h264_qpel_pixels_tab[1][12] = ff_put_h264_qpel8_mc03_lasx; + c->put_h264_qpel_pixels_tab[1][13] = ff_put_h264_qpel8_mc13_lasx; + c->put_h264_qpel_pixels_tab[1][14] = ff_put_h264_qpel8_mc23_lasx; + c->put_h264_qpel_pixels_tab[1][15] = ff_put_h264_qpel8_mc33_lasx; + c->avg_h264_qpel_pixels_tab[1][0] = ff_avg_h264_qpel8_mc00_lasx; + c->avg_h264_qpel_pixels_tab[1][1] = ff_avg_h264_qpel8_mc10_lasx; + c->avg_h264_qpel_pixels_tab[1][2] = ff_avg_h264_qpel8_mc20_lasx; + c->avg_h264_qpel_pixels_tab[1][3] = ff_avg_h264_qpel8_mc30_lasx; + c->avg_h264_qpel_pixels_tab[1][5] = ff_avg_h264_qpel8_mc11_lasx; + c->avg_h264_qpel_pixels_tab[1][6] = ff_avg_h264_qpel8_mc21_lasx; + c->avg_h264_qpel_pixels_tab[1][7] = ff_avg_h264_qpel8_mc31_lasx; + c->avg_h264_qpel_pixels_tab[1][8] = ff_avg_h264_qpel8_mc02_lasx; + c->avg_h264_qpel_pixels_tab[1][9] = ff_avg_h264_qpel8_mc12_lasx; + c->avg_h264_qpel_pixels_tab[1][10] = ff_avg_h264_qpel8_mc22_lasx; + c->avg_h264_qpel_pixels_tab[1][11] = ff_avg_h264_qpel8_mc32_lasx; + c->avg_h264_qpel_pixels_tab[1][13] = ff_avg_h264_qpel8_mc13_lasx; + c->avg_h264_qpel_pixels_tab[1][14] = ff_avg_h264_qpel8_mc23_lasx; + c->avg_h264_qpel_pixels_tab[1][15] = ff_avg_h264_qpel8_mc33_lasx; + } + } +} diff --git a/libavcodec/loongarch/h264qpel_lasx.c b/libavcodec/loongarch/h264qpel_lasx.c new file mode 100644 index 0000000000..1c142e510e --- /dev/null +++ b/libavcodec/loongarch/h264qpel_lasx.c @@ -0,0 +1,2038 @@ +/* + * Loongson LASX optimized h264qpel + * + * Copyright (c) 2020 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 "h264qpel_lasx.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "libavutil/attributes.h" + +static const uint8_t luma_mask_arr[16 * 6] __attribute__((aligned(0x40))) = { + /* 8 width cases */ + 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, + 0, 5, 1, 6, 2, 7, 3, 8, 4, 9, 5, 10, 6, 11, 7, 12, + 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, + 1, 4, 2, 5, 3, 6, 4, 7, 5, 8, 6, 9, 7, 10, 8, 11, + 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10 +}; + +#define AVC_HORZ_FILTER_SH(in0, in1, mask0, mask1, mask2) \ +( { \ + __m256i out0_m; \ + __m256i tmp0_m; \ + \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask0); \ + out0_m = __lasx_xvhaddw_h_b(tmp0_m, tmp0_m); \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask1); \ + out0_m = __lasx_xvdp2add_h_b(out0_m, minus5b, tmp0_m); \ + tmp0_m = __lasx_xvshuf_b(in1, in0, mask2); \ + out0_m = __lasx_xvdp2add_h_b(out0_m, plus20b, tmp0_m); \ + \ + out0_m; \ +} ) + +#define AVC_DOT_SH3_SH(in0, in1, in2, coeff0, coeff1, coeff2) \ +( { \ + __m256i out0_m; \ + \ + out0_m = __lasx_xvdp2_h_b(in0, coeff0); \ + DUP2_ARG3(__lasx_xvdp2add_h_b, out0_m, in1, coeff1, out0_m,\ + in2, coeff2, out0_m, out0_m); \ + \ + out0_m; \ +} ) + +static av_always_inline +void avc_luma_hv_qrt_and_aver_dst_16x16_lasx(uint8_t *src_x, + uint8_t *src_y, + uint8_t *dst, ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + uint32_t loop_cnt; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tmp0, tmp1; + __m256i src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + __m256i src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + __m256i src_vt7, src_vt8; + __m256i src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h, src_vt54_h; + __m256i src_vt65_h, src_vt76_h, src_vt87_h, filt0, filt1, filt2; + __m256i hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + __m256i vt_out3, out0, out1, out2, out3; + __m256i minus5b = __lasx_xvldi(0xFB); + __m256i plus20b = __lasx_xvldi(20); + + filt0 = __lasx_xvreplgr2vr_h(filt_const0); + filt1 = __lasx_xvreplgr2vr_h(filt_const1); + filt2 = __lasx_xvreplgr2vr_h(filt_const2); + + mask0 = __lasx_xvld(luma_mask_arr, 0); + DUP2_ARG2(__lasx_xvld, luma_mask_arr, 32, luma_mask_arr, 64, mask1, mask2); + src_vt0 = __lasx_xvld(src_y, 0); + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, src_y, stride_3x, + src_y, stride_4x, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += stride_4x; + + src_vt0 = __lasx_xvxori_b(src_vt0, 128); + DUP4_ARG2(__lasx_xvxori_b, src_vt1, 128, src_vt2, 128, src_vt3, 128, + src_vt4, 128, src_vt1, src_vt2, src_vt3, src_vt4); + + for (loop_cnt = 4; loop_cnt--;) { + src_hz0 = __lasx_xvld(src_x, 0); + DUP2_ARG2(__lasx_xvldx, src_x, stride, src_x, stride_2x, + src_hz1, src_hz2); + src_hz3 = __lasx_xvldx(src_x, stride_3x); + src_x += stride_4x; + src_hz0 = __lasx_xvpermi_d(src_hz0, 0x94); + src_hz1 = __lasx_xvpermi_d(src_hz1, 0x94); + src_hz2 = __lasx_xvpermi_d(src_hz2, 0x94); + src_hz3 = __lasx_xvpermi_d(src_hz3, 0x94); + DUP4_ARG2(__lasx_xvxori_b, src_hz0, 128, src_hz1, 128, src_hz2, 128, + src_hz3, 128, src_hz0, src_hz1, src_hz2, src_hz3); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + hz_out0 = __lasx_xvssrarni_b_h(hz_out1, hz_out0, 5); + hz_out2 = __lasx_xvssrarni_b_h(hz_out3, hz_out2, 5); + + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, + src_y, stride_3x, src_y, stride_4x, + src_vt5, src_vt6, src_vt7, src_vt8); + src_y += stride_4x; + + DUP4_ARG2(__lasx_xvxori_b, src_vt5, 128, src_vt6, 128, src_vt7, 128, + src_vt8, 128, src_vt5, src_vt6, src_vt7, src_vt8); + + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_vt4, 0x02, src_vt1, src_vt5, + 0x02, src_vt2, src_vt6, 0x02, src_vt3, src_vt7, 0x02, + src_vt0, src_vt1, src_vt2, src_vt3); + src_vt87_h = __lasx_xvpermi_q(src_vt4, src_vt8, 0x02); + DUP4_ARG2(__lasx_xvilvh_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_hz0, src_hz1, src_hz2, src_hz3); + DUP4_ARG2(__lasx_xvilvl_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_vt0, src_vt1, src_vt2, src_vt3); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x02, src_vt1, src_hz1, + 0x02, src_vt2, src_hz2, 0x02, src_vt3, src_hz3, 0x02, + src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x13, src_vt1, src_hz1, + 0x13, src_vt2, src_hz2, 0x13, src_vt3, src_hz3, 0x13, + src_vt54_h, src_vt65_h, src_vt76_h, src_vt87_h); + vt_out0 = AVC_DOT_SH3_SH(src_vt10_h, src_vt32_h, src_vt54_h, filt0, + filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_h, src_vt43_h, src_vt65_h, filt0, + filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_h, src_vt54_h, src_vt76_h, filt0, + filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_h, src_vt65_h, src_vt87_h, filt0, + filt1, filt2); + vt_out0 = __lasx_xvssrarni_b_h(vt_out1, vt_out0, 5); + vt_out2 = __lasx_xvssrarni_b_h(vt_out3, vt_out2, 5); + + DUP2_ARG2(__lasx_xvaddwl_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out0, out2); + DUP2_ARG2(__lasx_xvaddwh_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out1, out3); + tmp0 = __lasx_xvssrarni_b_h(out1, out0, 1); + tmp1 = __lasx_xvssrarni_b_h(out3, out2, 1); + + DUP2_ARG2(__lasx_xvxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + out0 = __lasx_xvld(dst, 0); + DUP2_ARG2(__lasx_xvldx, dst, stride, dst, stride_2x, out1, out2); + out3 = __lasx_xvldx(dst, stride_3x); + out0 = __lasx_xvpermi_q(out0, out2, 0x02); + out1 = __lasx_xvpermi_q(out1, out3, 0x02); + out2 = __lasx_xvilvl_d(out1, out0); + out3 = __lasx_xvilvh_d(out1, out0); + out0 = __lasx_xvpermi_q(out2, out3, 0x02); + out1 = __lasx_xvpermi_q(out2, out3, 0x13); + tmp0 = __lasx_xvavgr_bu(out0, tmp0); + tmp1 = __lasx_xvavgr_bu(out1, tmp1); + + __lasx_xvstelm_d(tmp0, dst, 0, 0); + __lasx_xvstelm_d(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 0, 0); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 0, 1); + + __lasx_xvstelm_d(tmp0, dst, 8, 2); + __lasx_xvstelm_d(tmp0, dst + stride, 8, 3); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 8, 2); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 8, 3); + + dst += stride_4x; + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } +} + +static av_always_inline void +avc_luma_hv_qrt_16x16_lasx(uint8_t *src_x, uint8_t *src_y, + uint8_t *dst, ptrdiff_t stride) +{ + const int16_t filt_const0 = 0xfb01; + const int16_t filt_const1 = 0x1414; + const int16_t filt_const2 = 0x1fb; + uint32_t loop_cnt; + ptrdiff_t stride_2x = stride << 1; + ptrdiff_t stride_3x = stride_2x + stride; + ptrdiff_t stride_4x = stride << 2; + __m256i tmp0, tmp1; + __m256i src_hz0, src_hz1, src_hz2, src_hz3, mask0, mask1, mask2; + __m256i src_vt0, src_vt1, src_vt2, src_vt3, src_vt4, src_vt5, src_vt6; + __m256i src_vt7, src_vt8; + __m256i src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h, src_vt54_h; + __m256i src_vt65_h, src_vt76_h, src_vt87_h, filt0, filt1, filt2; + __m256i hz_out0, hz_out1, hz_out2, hz_out3, vt_out0, vt_out1, vt_out2; + __m256i vt_out3, out0, out1, out2, out3; + __m256i minus5b = __lasx_xvldi(0xFB); + __m256i plus20b = __lasx_xvldi(20); + + filt0 = __lasx_xvreplgr2vr_h(filt_const0); + filt1 = __lasx_xvreplgr2vr_h(filt_const1); + filt2 = __lasx_xvreplgr2vr_h(filt_const2); + + mask0 = __lasx_xvld(luma_mask_arr, 0); + DUP2_ARG2(__lasx_xvld, luma_mask_arr, 32, luma_mask_arr, 64, mask1, mask2); + src_vt0 = __lasx_xvld(src_y, 0); + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, src_y, stride_3x, + src_y, stride_4x, src_vt1, src_vt2, src_vt3, src_vt4); + src_y += stride_4x; + + src_vt0 = __lasx_xvxori_b(src_vt0, 128); + DUP4_ARG2(__lasx_xvxori_b, src_vt1, 128, src_vt2, 128, src_vt3, 128, + src_vt4, 128, src_vt1, src_vt2, src_vt3, src_vt4); + + for (loop_cnt = 4; loop_cnt--;) { + src_hz0 = __lasx_xvld(src_x, 0); + DUP2_ARG2(__lasx_xvldx, src_x, stride, src_x, stride_2x, + src_hz1, src_hz2); + src_hz3 = __lasx_xvldx(src_x, stride_3x); + src_x += stride_4x; + src_hz0 = __lasx_xvpermi_d(src_hz0, 0x94); + src_hz1 = __lasx_xvpermi_d(src_hz1, 0x94); + src_hz2 = __lasx_xvpermi_d(src_hz2, 0x94); + src_hz3 = __lasx_xvpermi_d(src_hz3, 0x94); + DUP4_ARG2(__lasx_xvxori_b, src_hz0, 128, src_hz1, 128, src_hz2, 128, + src_hz3, 128, src_hz0, src_hz1, src_hz2, src_hz3); + + hz_out0 = AVC_HORZ_FILTER_SH(src_hz0, src_hz0, mask0, mask1, mask2); + hz_out1 = AVC_HORZ_FILTER_SH(src_hz1, src_hz1, mask0, mask1, mask2); + hz_out2 = AVC_HORZ_FILTER_SH(src_hz2, src_hz2, mask0, mask1, mask2); + hz_out3 = AVC_HORZ_FILTER_SH(src_hz3, src_hz3, mask0, mask1, mask2); + hz_out0 = __lasx_xvssrarni_b_h(hz_out1, hz_out0, 5); + hz_out2 = __lasx_xvssrarni_b_h(hz_out3, hz_out2, 5); + + DUP4_ARG2(__lasx_xvldx, src_y, stride, src_y, stride_2x, + src_y, stride_3x, src_y, stride_4x, + src_vt5, src_vt6, src_vt7, src_vt8); + src_y += stride_4x; + + DUP4_ARG2(__lasx_xvxori_b, src_vt5, 128, src_vt6, 128, src_vt7, 128, + src_vt8, 128, src_vt5, src_vt6, src_vt7, src_vt8); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_vt4, 0x02, src_vt1, src_vt5, + 0x02, src_vt2, src_vt6, 0x02, src_vt3, src_vt7, 0x02, + src_vt0, src_vt1, src_vt2, src_vt3); + src_vt87_h = __lasx_xvpermi_q(src_vt4, src_vt8, 0x02); + DUP4_ARG2(__lasx_xvilvh_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_hz0, src_hz1, src_hz2, src_hz3); + DUP4_ARG2(__lasx_xvilvl_b, src_vt1, src_vt0, src_vt2, src_vt1, + src_vt3, src_vt2, src_vt87_h, src_vt3, + src_vt0, src_vt1, src_vt2, src_vt3); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x02, src_vt1, + src_hz1, 0x02, src_vt2, src_hz2, 0x02, src_vt3, src_hz3, + 0x02, src_vt10_h, src_vt21_h, src_vt32_h, src_vt43_h); + DUP4_ARG3(__lasx_xvpermi_q, src_vt0, src_hz0, 0x13, src_vt1, + src_hz1, 0x13, src_vt2, src_hz2, 0x13, src_vt3, src_hz3, + 0x13, src_vt54_h, src_vt65_h, src_vt76_h, src_vt87_h); + + vt_out0 = AVC_DOT_SH3_SH(src_vt10_h, src_vt32_h, src_vt54_h, + filt0, filt1, filt2); + vt_out1 = AVC_DOT_SH3_SH(src_vt21_h, src_vt43_h, src_vt65_h, + filt0, filt1, filt2); + vt_out2 = AVC_DOT_SH3_SH(src_vt32_h, src_vt54_h, src_vt76_h, + filt0, filt1, filt2); + vt_out3 = AVC_DOT_SH3_SH(src_vt43_h, src_vt65_h, src_vt87_h, + filt0, filt1, filt2); + vt_out0 = __lasx_xvssrarni_b_h(vt_out1, vt_out0, 5); + vt_out2 = __lasx_xvssrarni_b_h(vt_out3, vt_out2, 5); + + DUP2_ARG2(__lasx_xvaddwl_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out0, out2); + DUP2_ARG2(__lasx_xvaddwh_h_b, hz_out0, vt_out0, hz_out2, vt_out2, + out1, out3); + tmp0 = __lasx_xvssrarni_b_h(out1, out0, 1); + tmp1 = __lasx_xvssrarni_b_h(out3, out2, 1); + + DUP2_ARG2(__lasx_xvxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lasx_xvstelm_d(tmp0, dst, 0, 0); + __lasx_xvstelm_d(tmp0, dst + stride, 0, 1); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 0, 0); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 0, 1); + + __lasx_xvstelm_d(tmp0, dst, 8, 2); + __lasx_xvstelm_d(tmp0, dst + stride, 8, 3); + __lasx_xvstelm_d(tmp1, dst + stride_2x, 8, 2); + __lasx_xvstelm_d(tmp1, dst + stride_3x, 8, 3); + + dst += stride_4x; + src_vt0 = src_vt4; + src_vt1 = src_vt5; + src_vt2 = src_vt6; + src_vt3 = src_vt7; + src_vt4 = src_vt8; + } +} + +/* put_pixels8_8_inline_asm: dst = src */ +static av_always_inline void +put_pixels8_8_inline_asm(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint64_t tmp[8]; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "ld.d %[tmp0], %[src], 0x0 \n\t" + "ldx.d %[tmp1], %[src], %[stride] \n\t" + "ldx.d %[tmp2], %[src], %[stride_2] \n\t" + "ldx.d %[tmp3], %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "ld.d %[tmp4], %[src], 0x0 \n\t" + "ldx.d %[tmp5], %[src], %[stride] \n\t" + "ldx.d %[tmp6], %[src], %[stride_2] \n\t" + "ldx.d %[tmp7], %[src], %[stride_3] \n\t" + + "st.d %[tmp0], %[dst], 0x0 \n\t" + "stx.d %[tmp1], %[dst], %[stride] \n\t" + "stx.d %[tmp2], %[dst], %[stride_2] \n\t" + "stx.d %[tmp3], %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "st.d %[tmp4], %[dst], 0x0 \n\t" + "stx.d %[tmp5], %[dst], %[stride] \n\t" + "stx.d %[tmp6], %[dst], %[stride_2] \n\t" + "stx.d %[tmp7], %[dst], %[stride_3] \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]), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), + [dst]"+&r"(dst), [src]"+&r"(src) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels8_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vstelm.d $vr0, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr1, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr2, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr3, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[stride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +put_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x08 \n\t" + "vld $vr10, %[half], 0x10 \n\t" + "vld $vr11, %[half], 0x18 \n\t" + "vld $vr12, %[half], 0x20 \n\t" + "vld $vr13, %[half], 0x28 \n\t" + "vld $vr14, %[half], 0x30 \n\t" + "vld $vr15, %[half], 0x38 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \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" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [srcStride]"r"(srcStride), [dstStride]"r"(dstStride) + : "memory" + ); +} + +/* avg_pixels8_8_lsx : dst = avg(src, dst) + * put_pixels8_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels8_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels8_l2_8_lsx(uint8_t *dst, const uint8_t *src, const uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x08 \n\t" + "vld $vr10, %[half], 0x10 \n\t" + "vld $vr11, %[half], 0x18 \n\t" + "vld $vr12, %[half], 0x20 \n\t" + "vld $vr13, %[half], 0x28 \n\t" + "vld $vr14, %[half], 0x30 \n\t" + "vld $vr15, %[half], 0x38 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "slli.d %[stride_2], %[dstStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[dstStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \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" + "vstelm.d $vr4, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr5, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr6, %[dst], 0, 0 \n\t" + "add.d %[dst], %[dst], %[dstStride] \n\t" + "vstelm.d $vr7, %[dst], 0, 0 \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [half]"+&r"(half), + [src]"+&r"(src), [stride_2]"=&r"(stride_2), + [stride_3]"=&r"(stride_3), [stride_4]"=&r"(stride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +/* put_pixels16_8_lsx: dst = src */ +static av_always_inline void +put_pixels16_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + : [dst]"+&r"(dst), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels16_8_lsx(uint8_t *dst, const uint8_t *src, ptrdiff_t stride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + __asm__ volatile ( + /* h0~h7 */ + "slli.d %[stride_2], %[stride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[stride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[stride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[stride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[stride] \n\t" + "vldx $vr10, %[tmp], %[stride_2] \n\t" + "vldx $vr11, %[tmp], %[stride_3] \n\t" + "add.d %[tmp], %[tmp], %[stride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[stride] \n\t" + "vldx $vr14, %[tmp], %[stride_2] \n\t" + "vldx $vr15, %[tmp], %[stride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[stride] \n\t" + "vstx $vr2, %[dst], %[stride_2] \n\t" + "vstx $vr3, %[dst], %[stride_3] \n\t" + "add.d %[dst], %[dst], %[stride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[stride] \n\t" + "vstx $vr6, %[dst], %[stride_2] \n\t" + "vstx $vr7, %[dst], %[stride_3] \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4) + : [stride]"r"(stride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +put_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + ptrdiff_t stride_2, stride_3, stride_4; + ptrdiff_t dstride_2, dstride_3, dstride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "slli.d %[dstride_2], %[dstStride], 1 \n\t" + "add.d %[dstride_3], %[dstride_2], %[dstStride] \n\t" + "slli.d %[dstride_4], %[dstride_2], 1 \n\t" + /* h0~h7 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x10 \n\t" + "vld $vr10, %[half], 0x20 \n\t" + "vld $vr11, %[half], 0x30 \n\t" + "vld $vr12, %[half], 0x40 \n\t" + "vld $vr13, %[half], 0x50 \n\t" + "vld $vr14, %[half], 0x60 \n\t" + "vld $vr15, %[half], 0x70 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x80 \n\t" + "vld $vr9, %[half], 0x90 \n\t" + "vld $vr10, %[half], 0xa0 \n\t" + "vld $vr11, %[half], 0xb0 \n\t" + "vld $vr12, %[half], 0xc0 \n\t" + "vld $vr13, %[half], 0xd0 \n\t" + "vld $vr14, %[half], 0xe0 \n\t" + "vld $vr15, %[half], 0xf0 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + : [dst]"+&r"(dst), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), [dstride_2]"=&r"(dstride_2), + [dstride_3]"=&r"(dstride_3), [dstride_4]"=&r"(dstride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +/* avg_pixels16_8_lsx : dst = avg(src, dst) + * put_pixels16_l2_8_lsx: dst = avg(src, half) , half stride is 8. + * avg_pixels16_l2_8_lsx: dst = avg(avg(src, half), dst) , half stride is 8.*/ +static av_always_inline void +avg_pixels16_l2_8_lsx(uint8_t *dst, const uint8_t *src, uint8_t *half, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + uint8_t *tmp = dst; + ptrdiff_t stride_2, stride_3, stride_4; + ptrdiff_t dstride_2, dstride_3, dstride_4; + __asm__ volatile ( + "slli.d %[stride_2], %[srcStride], 1 \n\t" + "add.d %[stride_3], %[stride_2], %[srcStride] \n\t" + "slli.d %[stride_4], %[stride_2], 1 \n\t" + "slli.d %[dstride_2], %[dstStride], 1 \n\t" + "add.d %[dstride_3], %[dstride_2], %[dstStride] \n\t" + "slli.d %[dstride_4], %[dstride_2], 1 \n\t" + /* h0~h7 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + + "vld $vr8, %[half], 0x00 \n\t" + "vld $vr9, %[half], 0x10 \n\t" + "vld $vr10, %[half], 0x20 \n\t" + "vld $vr11, %[half], 0x30 \n\t" + "vld $vr12, %[half], 0x40 \n\t" + "vld $vr13, %[half], 0x50 \n\t" + "vld $vr14, %[half], 0x60 \n\t" + "vld $vr15, %[half], 0x70 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[dstride_2] \n\t" + "vldx $vr11, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[dstride_2] \n\t" + "vldx $vr15, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + + /* h8~h15 */ + "vld $vr0, %[src], 0 \n\t" + "vldx $vr1, %[src], %[srcStride] \n\t" + "vldx $vr2, %[src], %[stride_2] \n\t" + "vldx $vr3, %[src], %[stride_3] \n\t" + "add.d %[src], %[src], %[stride_4] \n\t" + "vld $vr4, %[src], 0 \n\t" + "vldx $vr5, %[src], %[srcStride] \n\t" + "vldx $vr6, %[src], %[stride_2] \n\t" + "vldx $vr7, %[src], %[stride_3] \n\t" + + "vld $vr8, %[half], 0x80 \n\t" + "vld $vr9, %[half], 0x90 \n\t" + "vld $vr10, %[half], 0xa0 \n\t" + "vld $vr11, %[half], 0xb0 \n\t" + "vld $vr12, %[half], 0xc0 \n\t" + "vld $vr13, %[half], 0xd0 \n\t" + "vld $vr14, %[half], 0xe0 \n\t" + "vld $vr15, %[half], 0xf0 \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vld $vr8, %[tmp], 0 \n\t" + "vldx $vr9, %[tmp], %[dstStride] \n\t" + "vldx $vr10, %[tmp], %[dstride_2] \n\t" + "vldx $vr11, %[tmp], %[dstride_3] \n\t" + "add.d %[tmp], %[tmp], %[dstride_4] \n\t" + "vld $vr12, %[tmp], 0 \n\t" + "vldx $vr13, %[tmp], %[dstStride] \n\t" + "vldx $vr14, %[tmp], %[dstride_2] \n\t" + "vldx $vr15, %[tmp], %[dstride_3] \n\t" + + "vavgr.bu $vr0, $vr8, $vr0 \n\t" + "vavgr.bu $vr1, $vr9, $vr1 \n\t" + "vavgr.bu $vr2, $vr10, $vr2 \n\t" + "vavgr.bu $vr3, $vr11, $vr3 \n\t" + "vavgr.bu $vr4, $vr12, $vr4 \n\t" + "vavgr.bu $vr5, $vr13, $vr5 \n\t" + "vavgr.bu $vr6, $vr14, $vr6 \n\t" + "vavgr.bu $vr7, $vr15, $vr7 \n\t" + + "vst $vr0, %[dst], 0 \n\t" + "vstx $vr1, %[dst], %[dstStride] \n\t" + "vstx $vr2, %[dst], %[dstride_2] \n\t" + "vstx $vr3, %[dst], %[dstride_3] \n\t" + "add.d %[dst], %[dst], %[dstride_4] \n\t" + "vst $vr4, %[dst], 0 \n\t" + "vstx $vr5, %[dst], %[dstStride] \n\t" + "vstx $vr6, %[dst], %[dstride_2] \n\t" + "vstx $vr7, %[dst], %[dstride_3] \n\t" + : [dst]"+&r"(dst), [tmp]"+&r"(tmp), [half]"+&r"(half), [src]"+&r"(src), + [stride_2]"=&r"(stride_2), [stride_3]"=&r"(stride_3), + [stride_4]"=&r"(stride_4), [dstride_2]"=&r"(dstride_2), + [dstride_3]"=&r"(dstride_3), [dstride_4]"=&r"(dstride_4) + : [dstStride]"r"(dstStride), [srcStride]"r"(srcStride) + : "memory" + ); +} + +#define QPEL8_H_LOWPASS(out_v) \ + src00 = __lasx_xvld(src, - 2); \ + src += srcStride; \ + src10 = __lasx_xvld(src, - 2); \ + src += srcStride; \ + src00 = __lasx_xvpermi_q(src00, src10, 0x02); \ + src01 = __lasx_xvshuf_b(src00, src00, (__m256i)mask1); \ + src02 = __lasx_xvshuf_b(src00, src00, (__m256i)mask2); \ + src03 = __lasx_xvshuf_b(src00, src00, (__m256i)mask3); \ + src04 = __lasx_xvshuf_b(src00, src00, (__m256i)mask4); \ + src05 = __lasx_xvshuf_b(src00, src00, (__m256i)mask5); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, src02, src03, src01, src04, src02, src01);\ + src00 = __lasx_xvaddwl_h_bu(src00, src05); \ + src02 = __lasx_xvmul_h(src02, h_20); \ + src01 = __lasx_xvmul_h(src01, h_5); \ + src02 = __lasx_xvssub_h(src02, src01); \ + src02 = __lasx_xvsadd_h(src02, src00); \ + src02 = __lasx_xvsadd_h(src02, h_16); \ + out_v = __lasx_xvssrani_bu_h(src02, src02, 5); \ + +static av_always_inline void +put_h264_qpel8_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, int dstStride, + int srcStride) +{ + int dstStride_2x = dstStride << 1; + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i out0, out1, out2, out3; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + QPEL8_H_LOWPASS(out0) + QPEL8_H_LOWPASS(out1) + QPEL8_H_LOWPASS(out2) + QPEL8_H_LOWPASS(out3) + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out2, dst, 0, 0); + __lasx_xvstelm_d(out2, dst + dstStride, 0, 2); + dst += dstStride_2x; + __lasx_xvstelm_d(out3, dst, 0, 0); + __lasx_xvstelm_d(out3, dst + dstStride, 0, 2); +} + +#define QPEL8_V_LOWPASS(src0, src1, src2, src3, src4, src5, src6, \ + tmp0, tmp1, tmp2, tmp3, tmp4, tmp5) \ +{ \ + tmp0 = __lasx_xvpermi_q(src0, src1, 0x02); \ + tmp1 = __lasx_xvpermi_q(src1, src2, 0x02); \ + tmp2 = __lasx_xvpermi_q(src2, src3, 0x02); \ + tmp3 = __lasx_xvpermi_q(src3, src4, 0x02); \ + tmp4 = __lasx_xvpermi_q(src4, src5, 0x02); \ + tmp5 = __lasx_xvpermi_q(src5, src6, 0x02); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, tmp2, tmp3, tmp1, tmp4, tmp2, tmp1); \ + tmp0 = __lasx_xvaddwl_h_bu(tmp0, tmp5); \ + tmp2 = __lasx_xvmul_h(tmp2, h_20); \ + tmp1 = __lasx_xvmul_h(tmp1, h_5); \ + tmp2 = __lasx_xvssub_h(tmp2, tmp1); \ + tmp2 = __lasx_xvsadd_h(tmp2, tmp0); \ + tmp2 = __lasx_xvsadd_h(tmp2, h_16); \ + tmp2 = __lasx_xvssrani_bu_h(tmp2, tmp2, 5); \ +} + +static av_always_inline void +put_h264_qpel8_v_lowpass_lasx(uint8_t *dst, uint8_t *src, int dstStride, + int srcStride) +{ + int srcStride_2x = srcStride << 1; + int dstStride_2x = dstStride << 1; + int srcStride_4x = srcStride << 2; + int srcStride_3x = srcStride_2x + srcStride; + __m256i src00, src01, src02, src03, src04, src05, src06; + __m256i src07, src08, src09, src10, src11, src12; + __m256i tmp00, tmp01, tmp02, tmp03, tmp04, tmp05; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + + DUP2_ARG2(__lasx_xvld, src - srcStride_2x, 0, src - srcStride, 0, + src00, src01); + src02 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src03, src04, src05, src06); + src += srcStride_4x; + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src07, src08, src09, src10); + src += srcStride_4x; + DUP2_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src11, src12); + + QPEL8_V_LOWPASS(src00, src01, src02, src03, src04, src05, src06, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src02, src03, src04, src05, src06, src07, src08, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src04, src05, src06, src07, src08, src09, src10, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src06, src07, src08, src09, src10, src11, src12, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + __lasx_xvstelm_d(tmp02, dst, 0, 0); + __lasx_xvstelm_d(tmp02, dst + dstStride, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_v_lowpass_lasx(uint8_t *dst, uint8_t *src, int dstStride, + int srcStride) +{ + int srcStride_2x = srcStride << 1; + int srcStride_4x = srcStride << 2; + int dstStride_2x = dstStride << 1; + int dstStride_4x = dstStride << 2; + int srcStride_3x = srcStride_2x + srcStride; + int dstStride_3x = dstStride_2x + dstStride; + __m256i src00, src01, src02, src03, src04, src05, src06; + __m256i src07, src08, src09, src10, src11, src12, tmp00; + __m256i tmp01, tmp02, tmp03, tmp04, tmp05, tmp06, tmp07, tmp08, tmp09; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + + + DUP2_ARG2(__lasx_xvld, src - srcStride_2x, 0, src - srcStride, 0, + src00, src01); + src02 = __lasx_xvld(src, 0); + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src03, src04, src05, src06); + src += srcStride_4x; + DUP4_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src, + srcStride_3x, src, srcStride_4x, src07, src08, src09, src10); + src += srcStride_4x; + DUP2_ARG2(__lasx_xvldx, src, srcStride, src, srcStride_2x, src11, src12); + + tmp06 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, + dst, dstStride_3x, dst, dstStride_4x, + tmp07, tmp02, tmp03, tmp04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, + tmp05, tmp00); + tmp01 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + + tmp06 = __lasx_xvpermi_q(tmp06, tmp07, 0x02); + tmp07 = __lasx_xvpermi_q(tmp02, tmp03, 0x02); + tmp08 = __lasx_xvpermi_q(tmp04, tmp05, 0x02); + tmp09 = __lasx_xvpermi_q(tmp00, tmp01, 0x02); + + QPEL8_V_LOWPASS(src00, src01, src02, src03, src04, src05, src06, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp06 = __lasx_xvavgr_bu(tmp06, tmp02); + __lasx_xvstelm_d(tmp06, dst, 0, 0); + __lasx_xvstelm_d(tmp06, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src02, src03, src04, src05, src06, src07, src08, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp07 = __lasx_xvavgr_bu(tmp07, tmp02); + __lasx_xvstelm_d(tmp07, dst, 0, 0); + __lasx_xvstelm_d(tmp07, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src04, src05, src06, src07, src08, src09, src10, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp08 = __lasx_xvavgr_bu(tmp08, tmp02); + __lasx_xvstelm_d(tmp08, dst, 0, 0); + __lasx_xvstelm_d(tmp08, dst + dstStride, 0, 2); + dst += dstStride_2x; + QPEL8_V_LOWPASS(src06, src07, src08, src09, src10, src11, src12, + tmp00, tmp01, tmp02, tmp03, tmp04, tmp05); + tmp09 = __lasx_xvavgr_bu(tmp09, tmp02); + __lasx_xvstelm_d(tmp09, dst, 0, 0); + __lasx_xvstelm_d(tmp09, dst + dstStride, 0, 2); +} + +#define QPEL8_HV_LOWPASS_H(tmp) \ +{ \ + src00 = __lasx_xvld(src, -2); \ + src += srcStride; \ + src10 = __lasx_xvld(src, -2); \ + src += srcStride; \ + src00 = __lasx_xvpermi_q(src00, src10, 0x02); \ + src01 = __lasx_xvshuf_b(src00, src00, (__m256i)mask1); \ + src02 = __lasx_xvshuf_b(src00, src00, (__m256i)mask2); \ + src03 = __lasx_xvshuf_b(src00, src00, (__m256i)mask3); \ + src04 = __lasx_xvshuf_b(src00, src00, (__m256i)mask4); \ + src05 = __lasx_xvshuf_b(src00, src00, (__m256i)mask5); \ + DUP2_ARG2(__lasx_xvaddwl_h_bu, src02, src03, src01, src04, src02, src01);\ + src00 = __lasx_xvaddwl_h_bu(src00, src05); \ + src02 = __lasx_xvmul_h(src02, h_20); \ + src01 = __lasx_xvmul_h(src01, h_5); \ + src02 = __lasx_xvssub_h(src02, src01); \ + tmp = __lasx_xvsadd_h(src02, src00); \ +} + +#define QPEL8_HV_LOWPASS_V(src0, src1, src2, src3, \ + src4, src5, temp0, temp1, \ + temp2, temp3, temp4, temp5, \ + out) \ +{ \ + DUP2_ARG2(__lasx_xvaddwl_w_h, src2, src3, src1, src4, temp0, temp2); \ + DUP2_ARG2(__lasx_xvaddwh_w_h, src2, src3, src1, src4, temp1, temp3); \ + temp4 = __lasx_xvaddwl_w_h(src0, src5); \ + temp5 = __lasx_xvaddwh_w_h(src0, src5); \ + temp0 = __lasx_xvmul_w(temp0, w_20); \ + temp1 = __lasx_xvmul_w(temp1, w_20); \ + temp2 = __lasx_xvmul_w(temp2, w_5); \ + temp3 = __lasx_xvmul_w(temp3, w_5); \ + temp0 = __lasx_xvssub_w(temp0, temp2); \ + temp1 = __lasx_xvssub_w(temp1, temp3); \ + temp0 = __lasx_xvsadd_w(temp0, temp4); \ + temp1 = __lasx_xvsadd_w(temp1, temp5); \ + temp0 = __lasx_xvsadd_w(temp0, w_512); \ + temp1 = __lasx_xvsadd_w(temp1, w_512); \ + temp0 = __lasx_xvssrani_hu_w(temp0, temp0, 10); \ + temp1 = __lasx_xvssrani_hu_w(temp1, temp1, 10); \ + temp0 = __lasx_xvpackev_d(temp1, temp0); \ + out = __lasx_xvssrani_bu_h(temp0, temp0, 0); \ +} + +static av_always_inline void +put_h264_qpel8_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m256i tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i w_20 = __lasx_xvldi(0x814); + __m256i w_5 = __lasx_xvldi(0x805); + __m256i w_512 = {512}; + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + w_512 = __lasx_xvreplve0_w(w_512); + + src -= srcStride << 1; + QPEL8_HV_LOWPASS_H(tmp0) + QPEL8_HV_LOWPASS_H(tmp2) + QPEL8_HV_LOWPASS_H(tmp4) + QPEL8_HV_LOWPASS_H(tmp6) + QPEL8_HV_LOWPASS_H(tmp8) + QPEL8_HV_LOWPASS_H(tmp10) + QPEL8_HV_LOWPASS_H(tmp12) + tmp11 = __lasx_xvpermi_q(tmp12, tmp10, 0x21); + tmp9 = __lasx_xvpermi_q(tmp10, tmp8, 0x21); + tmp7 = __lasx_xvpermi_q(tmp8, tmp6, 0x21); + tmp5 = __lasx_xvpermi_q(tmp6, tmp4, 0x21); + tmp3 = __lasx_xvpermi_q(tmp4, tmp2, 0x21); + tmp1 = __lasx_xvpermi_q(tmp2, tmp0, 0x21); + + QPEL8_HV_LOWPASS_V(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, src00, src01, + src02, src03, src04, src05, tmp0) + QPEL8_HV_LOWPASS_V(tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, src00, src01, + src02, src03, src04, src05, tmp2) + QPEL8_HV_LOWPASS_V(tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, src00, src01, + src02, src03, src04, src05, tmp4) + QPEL8_HV_LOWPASS_V(tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, src00, src01, + src02, src03, src04, src05, tmp6) + __lasx_xvstelm_d(tmp0, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp0, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, int dstStride, + int srcStride) +{ + int dstStride_2x = dstStride << 1; + int dstStride_4x = dstStride << 2; + int dstStride_3x = dstStride_2x + dstStride; + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i dst00, dst01, dst0, dst1, dst2, dst3; + __m256i out0, out1, out2, out3; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i h_16 = __lasx_xvldi(0x410); + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + + QPEL8_H_LOWPASS(out0) + QPEL8_H_LOWPASS(out1) + QPEL8_H_LOWPASS(out2) + QPEL8_H_LOWPASS(out3) + src00 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, dst, + dstStride_3x, dst, dstStride_4x, src01, src02, src03, src04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, src05, dst00); + dst01 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + dst0 = __lasx_xvpermi_q(src00, src01, 0x02); + dst1 = __lasx_xvpermi_q(src02, src03, 0x02); + dst2 = __lasx_xvpermi_q(src04, src05, 0x02); + dst3 = __lasx_xvpermi_q(dst00, dst01, 0x02); + dst0 = __lasx_xvavgr_bu(dst0, out0); + dst1 = __lasx_xvavgr_bu(dst1, out1); + dst2 = __lasx_xvavgr_bu(dst2, out2); + dst3 = __lasx_xvavgr_bu(dst3, out3); + __lasx_xvstelm_d(dst0, dst, 0, 0); + __lasx_xvstelm_d(dst0, dst + dstStride, 0, 2); + __lasx_xvstelm_d(dst1, dst + dstStride_2x, 0, 0); + __lasx_xvstelm_d(dst1, dst + dstStride_3x, 0, 2); + dst += dstStride_4x; + __lasx_xvstelm_d(dst2, dst, 0, 0); + __lasx_xvstelm_d(dst2, dst + dstStride, 0, 2); + __lasx_xvstelm_d(dst3, dst + dstStride_2x, 0, 0); + __lasx_xvstelm_d(dst3, dst + dstStride_3x, 0, 2); +} + +static av_always_inline void +avg_h264_qpel8_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + __m256i src00, src01, src02, src03, src04, src05, src10; + __m256i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m256i tmp7, tmp8, tmp9, tmp10, tmp11, tmp12; + __m256i h_20 = __lasx_xvldi(0x414); + __m256i h_5 = __lasx_xvldi(0x405); + __m256i w_20 = __lasx_xvldi(0x814); + __m256i w_5 = __lasx_xvldi(0x805); + __m256i w_512 = {512}; + __m256i mask1 = {0x0807060504030201, 0x0, 0x0807060504030201, 0x0}; + __m256i mask2 = {0x0908070605040302, 0x0, 0x0908070605040302, 0x0}; + __m256i mask3 = {0x0a09080706050403, 0x0, 0x0a09080706050403, 0x0}; + __m256i mask4 = {0x0b0a090807060504, 0x0, 0x0b0a090807060504, 0x0}; + __m256i mask5 = {0x0c0b0a0908070605, 0x0, 0x0c0b0a0908070605, 0x0}; + ptrdiff_t dstStride_2x = dstStride << 1; + ptrdiff_t dstStride_4x = dstStride << 2; + ptrdiff_t dstStride_3x = dstStride_2x + dstStride; + + w_512 = __lasx_xvreplve0_w(w_512); + + src -= srcStride << 1; + QPEL8_HV_LOWPASS_H(tmp0) + QPEL8_HV_LOWPASS_H(tmp2) + QPEL8_HV_LOWPASS_H(tmp4) + QPEL8_HV_LOWPASS_H(tmp6) + QPEL8_HV_LOWPASS_H(tmp8) + QPEL8_HV_LOWPASS_H(tmp10) + QPEL8_HV_LOWPASS_H(tmp12) + tmp11 = __lasx_xvpermi_q(tmp12, tmp10, 0x21); + tmp9 = __lasx_xvpermi_q(tmp10, tmp8, 0x21); + tmp7 = __lasx_xvpermi_q(tmp8, tmp6, 0x21); + tmp5 = __lasx_xvpermi_q(tmp6, tmp4, 0x21); + tmp3 = __lasx_xvpermi_q(tmp4, tmp2, 0x21); + tmp1 = __lasx_xvpermi_q(tmp2, tmp0, 0x21); + + QPEL8_HV_LOWPASS_V(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, src00, src01, + src02, src03, src04, src05, tmp0) + QPEL8_HV_LOWPASS_V(tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, src00, src01, + src02, src03, src04, src05, tmp2) + QPEL8_HV_LOWPASS_V(tmp4, tmp5, tmp6, tmp7, tmp8, tmp9, src00, src01, + src02, src03, src04, src05, tmp4) + QPEL8_HV_LOWPASS_V(tmp6, tmp7, tmp8, tmp9, tmp10, tmp11, src00, src01, + src02, src03, src04, src05, tmp6) + + src00 = __lasx_xvld(dst, 0); + DUP4_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, dst, + dstStride_3x, dst, dstStride_4x, src01, src02, src03, src04); + dst += dstStride_4x; + DUP2_ARG2(__lasx_xvldx, dst, dstStride, dst, dstStride_2x, src05, tmp8); + tmp9 = __lasx_xvldx(dst, dstStride_3x); + dst -= dstStride_4x; + tmp1 = __lasx_xvpermi_q(src00, src01, 0x02); + tmp3 = __lasx_xvpermi_q(src02, src03, 0x02); + tmp5 = __lasx_xvpermi_q(src04, src05, 0x02); + tmp7 = __lasx_xvpermi_q(tmp8, tmp9, 0x02); + tmp0 = __lasx_xvavgr_bu(tmp0, tmp1); + tmp2 = __lasx_xvavgr_bu(tmp2, tmp3); + tmp4 = __lasx_xvavgr_bu(tmp4, tmp5); + tmp6 = __lasx_xvavgr_bu(tmp6, tmp7); + __lasx_xvstelm_d(tmp0, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp0, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp2, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp4, dst, 0, 2); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 0); + dst += dstStride; + __lasx_xvstelm_d(tmp6, dst, 0, 2); +} + +static av_always_inline void +put_h264_qpel16_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); +} + +static av_always_inline void +avg_h264_qpel16_h_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + avg_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + avg_h264_qpel8_h_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_h_lowpass_lasx(dst+8, src+8, dstStride, srcStride); +} + +static void put_h264_qpel16_v_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + put_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +static void avg_h264_qpel16_v_lowpass_lasx(uint8_t *dst, const uint8_t *src, + int dstStride, int srcStride) +{ + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); + src += 8*srcStride; + dst += 8*dstStride; + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, dstStride, srcStride); + avg_h264_qpel8_v_lowpass_lasx(dst+8, (uint8_t*)src+8, dstStride, srcStride); +} + +static void put_h264_qpel16_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + put_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + put_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + put_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); +} + +static void avg_h264_qpel16_hv_lowpass_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dstStride, ptrdiff_t srcStride) +{ + avg_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); + src += srcStride << 3; + dst += dstStride << 3; + avg_h264_qpel8_hv_lowpass_lasx(dst, src, dstStride, srcStride); + avg_h264_qpel8_hv_lowpass_lasx(dst + 8, src + 8, dstStride, srcStride); +} + +void ff_put_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_put_pixels8_8_mmi + * which implemented in hpeldsp_mmi.c */ + put_pixels8_8_inline_asm(dst, src, stride); +} + +void ff_put_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + /* in qpel8, the stride of half and height of block is 8 */ + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + put_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_put_h264_qpel8_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lasx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, stride, stride); +} + +void ff_put_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel8_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_v_lowpass_lasx(half, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_put_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_put_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + put_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_avg_pixels8_8_mmi + * which implemented in hpeldsp_mmi.c */ + avg_pixels8_8_lsx(dst, src, stride); +} + +void ff_avg_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[64]; + + put_h264_qpel8_h_lowpass_lasx(half, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_avg_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_v_lowpass_lasx(dst, (uint8_t*)src, stride, stride); +} + +void ff_avg_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel8_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 64; + + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfH, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_avg_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[128]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 64; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_hv_lowpass_lasx(halfHV, src, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfHV, stride, 8); +} + +void ff_avg_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t halfH[64]; + uint8_t halfV[64]; + + put_h264_qpel8_h_lowpass_lasx(halfH, src + stride, 8, stride); + put_h264_qpel8_v_lowpass_lasx(halfV, (uint8_t*)src + 1, 8, stride); + avg_pixels8_l2_8_lsx(dst, halfH, halfV, stride, 8); +} + +void ff_put_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_put_pixels16_8_mmi + * which implemented in hpeldsp_mmi.c */ + put_pixels16_8_lsx(dst, src, stride); +} + +void ff_put_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_put_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_put_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src - 2, (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_put_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src - 2, (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} + +void ff_put_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_v_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + put_h264_qpel16_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_put_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src + 1, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + put_pixels16_l2_8_lsx(dst, src+stride, half, stride, stride); +} + +void ff_put_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src + stride - 2, (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_put_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_put_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2) + 1, dst, stride); +} + +void ff_avg_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + /* In mmi optimization, it used function ff_avg_pixels16_8_mmi + * which implemented in hpeldsp_mmi.c */ + avg_pixels16_8_lsx(dst, src, stride); +} + +void ff_avg_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_h_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_h_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src+1, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src - 2, + (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_avg_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src - 2, + (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} + +void ff_avg_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_v_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avg_h264_qpel16_hv_lowpass_lasx(dst, src, stride, stride); +} + +void ff_avg_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfHV = temp; + uint8_t *const halfH = temp + 256; + + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + put_h264_qpel16_v_lowpass_lasx(halfH, src + 1, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t half[256]; + + put_h264_qpel16_v_lowpass_lasx(half, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, src + stride, half, stride, stride); +} + +void ff_avg_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2), + dst, stride); +} + +void ff_avg_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + uint8_t temp[512]; + uint8_t *const halfH = temp; + uint8_t *const halfHV = temp + 256; + + put_h264_qpel16_h_lowpass_lasx(halfH, src + stride, 16, stride); + put_h264_qpel16_hv_lowpass_lasx(halfHV, src, 16, stride); + avg_pixels16_l2_8_lsx(dst, halfH, halfHV, stride, 16); +} + +void ff_avg_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride) +{ + avc_luma_hv_qrt_and_aver_dst_16x16_lasx((uint8_t*)src + stride - 2, + (uint8_t*)src - (stride * 2) + 1, + dst, stride); +} diff --git a/libavcodec/loongarch/h264qpel_lasx.h b/libavcodec/loongarch/h264qpel_lasx.h new file mode 100644 index 0000000000..32b6b50917 --- /dev/null +++ b/libavcodec/loongarch/h264qpel_lasx.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2020 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_H264QPEL_LASX_H +#define AVCODEC_LOONGARCH_H264QPEL_LASX_H + +#include +#include +#include "libavcodec/h264.h" + +void ff_h264_h_lpf_luma_inter_lasx(uint8_t *src, int stride, + int alpha, int beta, int8_t *tc0); +void ff_h264_v_lpf_luma_inter_lasx(uint8_t *src, int stride, + int alpha, int beta, int8_t *tc0); +void ff_put_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_put_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel16_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); + +void ff_put_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc01_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc03_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_put_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride); +void ff_avg_h264_qpel8_mc00_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc10_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc20_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc30_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc11_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc21_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc31_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc02_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc12_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc22_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc32_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc13_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc23_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +void ff_avg_h264_qpel8_mc33_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t dst_stride); +#endif // #ifndef AVCODEC_LOONGARCH_H264QPEL_LASX_H diff --git a/libavcodec/loongarch/hpeldsp_init_loongarch.c b/libavcodec/loongarch/hpeldsp_init_loongarch.c new file mode 100644 index 0000000000..1690be5438 --- /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 0000000000..dd2ae173da --- /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 0000000000..2e035eade8 --- /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 0000000000..9d1d21cc18 --- /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 0000000000..1cfab0e028 --- /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 0000000000..cae8e7af58 --- /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 0000000000..a0d936b666 --- /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/vc1dsp_init_loongarch.c b/libavcodec/loongarch/vc1dsp_init_loongarch.c new file mode 100644 index 0000000000..e72a4a3203 --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_init_loongarch.c @@ -0,0 +1,67 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavcodec/vc1dsp.h" +#include "vc1dsp_loongarch.h" + +#define FN_ASSIGN(OP, X, Y, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[1][X+4*Y] = ff_##OP##vc1_mspel_mc##X##Y##INSN; \ + dsp->OP##vc1_mspel_pixels_tab[0][X+4*Y] = ff_##OP##vc1_mspel_mc##X##Y##_16##INSN + +#define FN_ASSIGN_V(OP, Y, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[0][4*Y] = ff_##OP##vc1_mspel_mc0##Y##_16##INSN + +#define FN_ASSIGN_H(OP, X, INSN) \ + dsp->OP##vc1_mspel_pixels_tab[0][X] = ff_##OP##vc1_mspel_mc##X##0_16##INSN + +av_cold void ff_vc1dsp_init_loongarch(VC1DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lasx(cpu_flags)) { + dsp->vc1_inv_trans_8x8 = ff_vc1_inv_trans_8x8_lasx; + dsp->vc1_inv_trans_4x8 = ff_vc1_inv_trans_4x8_lasx; + dsp->vc1_inv_trans_8x4 = ff_vc1_inv_trans_8x4_lasx; + dsp->vc1_inv_trans_4x4 = ff_vc1_inv_trans_4x4_lasx; + dsp->vc1_inv_trans_8x8_dc = ff_vc1_inv_trans_8x8_dc_lasx; + dsp->vc1_inv_trans_4x8_dc = ff_vc1_inv_trans_4x8_dc_lasx; + dsp->vc1_inv_trans_8x4_dc = ff_vc1_inv_trans_8x4_dc_lasx; + dsp->vc1_inv_trans_4x4_dc = ff_vc1_inv_trans_4x4_dc_lasx; + FN_ASSIGN(put_, 1, 1, _lasx); + FN_ASSIGN(put_, 1, 2, _lasx); + FN_ASSIGN(put_, 1, 3, _lasx); + FN_ASSIGN(put_, 2, 1, _lasx); + FN_ASSIGN(put_, 2, 2, _lasx); + FN_ASSIGN(put_, 2, 3, _lasx); + FN_ASSIGN(put_, 3, 1, _lasx); + FN_ASSIGN(put_, 3, 2, _lasx); + FN_ASSIGN(put_, 3, 3, _lasx); + FN_ASSIGN_V(put_, 1, _lasx); + FN_ASSIGN_V(put_, 2, _lasx); + FN_ASSIGN_V(put_, 3, _lasx); + FN_ASSIGN_H(put_, 1, _lasx); + FN_ASSIGN_H(put_, 2, _lasx); + FN_ASSIGN_H(put_, 3, _lasx); + dsp->put_no_rnd_vc1_chroma_pixels_tab[0] = ff_put_no_rnd_vc1_chroma_mc8_lasx; + } +} diff --git a/libavcodec/loongarch/vc1dsp_lasx.c b/libavcodec/loongarch/vc1dsp_lasx.c new file mode 100644 index 0000000000..40b8668f2b --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_lasx.c @@ -0,0 +1,1005 @@ +/* + * 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 "vc1dsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +void ff_vc1_inv_trans_8x8_lasx(int16_t block[64]) +{ + int32_t con_4 = 4; + int32_t con_64 = 64; + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4, t5, t6, t7, t8; + __m256i const_1 = {0x000c000c000c000c, 0x000c000c000c000c, + 0x000c000c000c000c, 0x000c000c000c000c}; + __m256i const_2 = {0xfff4000cfff4000c, 0xfff4000cfff4000c, + 0xfff4000cfff4000c, 0xfff4000cfff4000c}; + __m256i const_3 = {0x0006001000060010, 0x0006001000060010, + 0x0006001000060010, 0x0006001000060010}; + __m256i const_4 = {0xfff00006fff00006, 0xfff00006fff00006, + 0xfff00006fff00006, 0xfff00006fff00006}; + __m256i const_5 = {0x000f0010000f0010, 0x000f0010000f0010, + 0x000f0010000f0010, 0x000f0010000f0010}; + __m256i const_6 = {0x0004000900040009, 0x0004000900040009, + 0x0004000900040009, 0x0004000900040009}; + __m256i const_7 = {0xfffc000ffffc000f, 0xfffc000ffffc000f, + 0xfffc000ffffc000f, 0xfffc000ffffc000f}; + __m256i const_8 = {0xfff7fff0fff7fff0, 0xfff7fff0fff7fff0, + 0xfff7fff0fff7fff0, 0xfff7fff0fff7fff0}; + __m256i const_9 = {0xfff00009fff00009, 0xfff00009fff00009, + 0xfff00009fff00009, 0xfff00009fff00009}; + __m256i const_10 = {0x000f0004000f0004, 0x000f0004000f0004, + 0x000f0004000f0004, 0x000f0004000f0004}; + __m256i const_11 = {0xfff70004fff70004, 0xfff70004fff70004, + 0xfff70004fff70004, 0xfff70004fff70004}; + __m256i const_12 = {0xfff0000ffff0000f, 0xfff0000ffff0000f, + 0xfff0000ffff0000f, 0xfff0000ffff0000f}; + + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + /* first loops */ + DUP2_ARG2(__lasx_xvilvl_h, in2, in0, in3, in1, temp0, temp1); + t2 = __lasx_xvreplgr2vr_w(con_4); + DUP2_ARG3(__lasx_xvdp2add_w_h, t2, temp0, const_1, t2, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + t5 = __lasx_xvadd_w(t1, t3); + t6 = __lasx_xvadd_w(t2, t4); + t7 = __lasx_xvsub_w(t2, t4); + t8 = __lasx_xvsub_w(t1, t3); + + DUP2_ARG2(__lasx_xvilvh_h, in1, in0, in3, in2, temp0, temp1); + temp2 = __lasx_xvdp2_w_h(const_5, temp0); + t1 = __lasx_xvdp2add_w_h(temp2, temp1, const_6); + temp2 = __lasx_xvdp2_w_h(const_7, temp0); + t2 = __lasx_xvdp2add_w_h(temp2, temp1, const_8); + temp2 = __lasx_xvdp2_w_h(const_9, temp0); + t3 = __lasx_xvdp2add_w_h(temp2, temp1, const_10); + temp2 = __lasx_xvdp2_w_h(const_11, temp0); + t4 = __lasx_xvdp2add_w_h(temp2, temp1, const_12); + + DUP4_ARG2(__lasx_xvadd_w, t1, t5, t6, t2, t7, t3, t8, t4, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsub_w, t8, t4, t7, t3, t6, t2, t5, t1, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 3, temp1, 3, temp2, 3, temp3, 3, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsrai_w, in0, 3, in1, 3, in2, 3, in3, 3, + in0, in1, in2, in3); + + /* second loops */ + DUP4_ARG2(__lasx_xvpackev_h, temp1, temp0, temp3, temp2, in1, in0, + in3, in2, temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvilvl_w, temp1, temp0, temp3, temp2, t1, t3); + DUP2_ARG2(__lasx_xvilvh_w, temp1, temp0, temp3, temp2, t2, t4); + DUP4_ARG3(__lasx_xvpermi_q, t3, t1, 0x20, t3, t1, 0x31, t4, t2, 0x20, + t4, t2, 0x31, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_h, in1, in0, in3, in2, temp0, temp1); + t3 = __lasx_xvreplgr2vr_w(con_64); + DUP2_ARG3(__lasx_xvdp2add_w_h, t3, temp0, const_1, t3, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + t5 = __lasx_xvadd_w(t1, t3); + t6 = __lasx_xvadd_w(t2, t4); + t7 = __lasx_xvsub_w(t2, t4); + t8 = __lasx_xvsub_w(t1, t3); + + DUP2_ARG2(__lasx_xvilvh_h, in2, in0, in3, in1, temp0, temp1); + temp2 = __lasx_xvdp2_w_h(const_5, temp0); + t1 = __lasx_xvdp2add_w_h(temp2, temp1, const_6); + temp2 = __lasx_xvdp2_w_h(const_7, temp0); + t2 = __lasx_xvdp2add_w_h(temp2, temp1, const_8); + temp2 = __lasx_xvdp2_w_h(const_9, temp0); + t3 = __lasx_xvdp2add_w_h(temp2, temp1, const_10); + temp2 = __lasx_xvdp2_w_h(const_11, temp0); + t4 = __lasx_xvdp2add_w_h(temp2, temp1, const_12); + + DUP4_ARG2(__lasx_xvadd_w, t5, t1, t6, t2, t7, t3, t8, t4, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvsub_w, t8, t4, t7, t3, t6, t2, t5, t1, + in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvaddi_wu, in0, 1, in1, 1, in2, 1, in3, 1, + in0, in1, in2, in3); + DUP4_ARG3(__lasx_xvsrani_h_w, temp1, temp0, 7, temp3, temp2, 7, + in1, in0, 7, in3, in2, 7, t1, t2, t3, t4); + DUP4_ARG2(__lasx_xvpermi_d, t1, 0xD8, t2, 0xD8, t3, 0xD8, t4, 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_vc1_inv_trans_8x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3, in4, in5, in6, in7; + __m256i const_dc, temp0, temp1, temp2, temp3; + __m256i reg0, reg1, reg2, reg3; + + dc = (3 * dc + 1) >> 1; + dc = (3 * dc + 16) >> 5; + + const_dc = __lasx_xvreplgr2vr_h(dc); + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvldrepl_d, dst, 0, dst + stride, 0, dst + stride2, + 0, dst + stride3, 0, in4, in5, in6, in7); + + DUP4_ARG2(__lasx_xvilvl_d, in1, in0, in3, in2, in5, in4, in7, in6, + temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_vext2xv_hu_bu, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + + DUP4_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, temp2, + const_dc, temp3, const_dc, reg0, reg1, reg2, reg3); + DUP2_ARG3(__lasx_xvssrarni_bu_h, reg1, reg0, 0, reg3, reg2, 0, + temp0, temp1); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); + __lasx_xvstelm_d(temp1, dst, 0, 0); + __lasx_xvstelm_d(temp1, dst + stride, 0, 2); + __lasx_xvstelm_d(temp1, dst + stride2, 0, 1); + __lasx_xvstelm_d(temp1, dst + stride3, 0, 3); +} + +void ff_vc1_inv_trans_8x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + __m256i shift = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + __m256i const_64 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + __m256i const_1 = {0x00060010000C000C, 0x00060010000C000C, + 0x00060010000C000C, 0x00060010000C000C}; + __m256i const_2 = {0xFFF00006FFF4000C, 0xFFF00006FFF4000C, + 0xFFF00006FFF4000C, 0xFFF00006FFF4000C}; + __m256i const_3 = {0x0004000F00090010, 0x0004000F00090010, + 0x0004000F00090010, 0x0004000F00090010}; + __m256i const_4 = {0xFFF7FFFCFFF0000F, 0xFFF7FFFCFFF0000F, + 0xFFF7FFFCFFF0000F, 0xFFF7FFFCFFF0000F}; + __m256i const_5 = {0x000FFFF000040009, 0x000FFFF000040009, + 0x000FFFF000040009, 0x000FFFF000040009}; + __m256i const_6 = {0xFFF0FFF7000F0004, 0xFFF0FFF7000F0004, + 0xFFF0FFF7000F0004, 0xFFF0FFF7000F0004}; + __m256i const_7 = {0x0000000000000004, 0x0000000000000004, + 0x0000000000000004, 0x0000000000000004}; + __m256i const_8 = {0x0011001100110011, 0x0011001100110011, + 0x0011001100110011, 0x0011001100110011}; + __m256i const_9 = {0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011, + 0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011}; + __m256i const_10 = {0x000A0016000A0016, 0x000A0016000A0016, + 0x000A0016000A0016, 0x000A0016000A0016}; + __m256i const_11 = {0x0016FFF60016FFF6, 0x0016FFF60016FFF6, + 0x0016FFF60016FFF6, 0x0016FFF60016FFF6}; + __m256i in0, in1; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4; + + DUP2_ARG2(__lasx_xvld, block, 0, block, 32, in0, in1); + /* first loops */ + temp0 = __lasx_xvpermi_d(in0, 0xB1); + temp1 = __lasx_xvpermi_d(in1, 0xB1); + DUP2_ARG2(__lasx_xvilvl_h, temp0, in0, temp1, in1, temp0, temp1); + temp2 = __lasx_xvpickev_w(temp1, temp0); + temp3 = __lasx_xvpickod_w(temp1, temp0); + + DUP2_ARG2(__lasx_xvdp2_w_h, temp2, const_1, temp2, const_2, temp0, temp1); + t1 = __lasx_xvadd_w(temp0, const_7); + t2 = __lasx_xvadd_w(temp1, const_7); + temp0 = __lasx_xvpickev_w(t2, t1); + temp1 = __lasx_xvpickod_w(t2, t1); + t3 = __lasx_xvadd_w(temp0, temp1); + t4 = __lasx_xvsub_w(temp0, temp1); + t4 = __lasx_xvpermi_d(t4, 0xB1); + + DUP4_ARG2(__lasx_xvdp4_d_h, temp3, const_3, temp3, const_4, temp3, + const_5, temp3, const_6, t1, t2, temp0, temp1); + temp2 = __lasx_xvpickev_w(t2, t1); + temp3 = __lasx_xvpickev_w(temp1, temp0); + + t1 = __lasx_xvadd_w(temp2, t3); + t2 = __lasx_xvadd_w(temp3, t4); + temp0 = __lasx_xvsub_w(t4, temp3); + temp1 = __lasx_xvsub_w(t3, temp2); + /* second loops */ + DUP2_ARG3(__lasx_xvsrani_h_w, t2, t1, 3, temp1, temp0, 3, temp2, temp3); + temp3 = __lasx_xvshuf4i_h(temp3, 0x4E); + temp0 = __lasx_xvpermi_q(temp3, temp2, 0x20); + temp1 = __lasx_xvpermi_q(temp3, temp2, 0x31); + DUP2_ARG3(__lasx_xvdp2add_w_h, const_64, temp0, const_8, const_64, temp0, + const_9, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_10, temp1, const_11, t3, t4); + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvsub_w(t2, t4); + temp2 = __lasx_xvadd_w(t2, t4); + temp3 = __lasx_xvsub_w(t1, t3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 7, temp1, 7, temp2, 7, temp3, 7, + t1, t2, t3, t4); + + temp0 = __lasx_xvldrepl_d(dest, 0); + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, 0, + dest + stride3, 0, temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_vext2xv_wu_bu, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP4_ARG2(__lasx_xvadd_w, temp0, t1, temp1, t2, temp2, t3, temp3, t4, + t1, t2, t3, t4); + DUP4_ARG1(__lasx_xvclip255_w, t1, t2, t3, t4, t1, t2, t3, t4); + DUP2_ARG2(__lasx_xvpickev_h, t2, t1, t4, t3, temp0, temp1); + temp2 = __lasx_xvpickev_b(temp1, temp0); + temp0 = __lasx_xvperm_w(temp2, shift); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); +} + +void ff_vc1_inv_trans_8x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + __m256i in0, in1, in2, in3; + __m256i const_dc, temp0, temp1, reg0, reg1; + + dc = (3 * dc + 1) >> 1; + dc = (17 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_d, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_d, in1, in0, in3, in2, temp0, temp1); + DUP2_ARG1(__lasx_vext2xv_hu_bu, temp0, temp1, temp0, temp1); + DUP2_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, reg0, reg1); + temp0 = __lasx_xvssrarni_bu_h(reg1, reg0, 0); + __lasx_xvstelm_d(temp0, dest, 0, 0); + __lasx_xvstelm_d(temp0, dest + stride, 0, 2); + __lasx_xvstelm_d(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_d(temp0, dest + stride3, 0, 3); +} + +void ff_vc1_inv_trans_4x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3, in4, in5, in6, in7; + __m256i const_dc, temp0, temp1, temp2, temp3, reg0, reg1; + + dc = (17 * dc + 4) >> 3; + dc = (12 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dest + stride, 0, dest + stride2, + 0, dest + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvldrepl_w, dst, 0, dst + stride, 0, dst + stride2, + 0, dst + stride3, 0, in4, in5, in6, in7); + + DUP4_ARG2(__lasx_xvilvl_w, in1, in0, in3, in2, in5, in4, in7, in6, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvilvl_d, temp1, temp0, temp3, temp2, reg0, reg1); + DUP2_ARG1(__lasx_vext2xv_hu_bu, reg0, reg1, temp0, temp1); + DUP2_ARG2(__lasx_xvadd_h, temp0, const_dc, temp1, const_dc, reg0, reg1); + temp0 = __lasx_xvssrarni_bu_h(reg1, reg0, 0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dest + stride, 0, 1); + __lasx_xvstelm_w(temp0, dest + stride2, 0, 4); + __lasx_xvstelm_w(temp0, dest + stride3, 0, 5); + __lasx_xvstelm_w(temp0, dst, 0, 2); + __lasx_xvstelm_w(temp0, dst + stride, 0, 3); + __lasx_xvstelm_w(temp0, dst + stride2, 0, 6); + __lasx_xvstelm_w(temp0, dst + stride3, 0, 7); +} + +void ff_vc1_inv_trans_4x8_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + uint8_t *dst = dest + (stride2 << 1); + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2, t3, t4; + + __m256i const_1 = {0x0011001100110011, 0x0011001100110011, + 0x0011001100110011, 0x0011001100110011}; + __m256i const_2 = {0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011, + 0xFFEF0011FFEF0011, 0xFFEF0011FFEF0011}; + __m256i const_3 = {0x000A0016000A0016, 0x000A0016000A0016, + 0x000A0016000A0016, 0x000A0016000A0016}; + __m256i const_4 = {0x0016FFF60016FFF6, 0x0016FFF60016FFF6, + 0x0016FFF60016FFF6, 0x0016FFF60016FFF6}; + __m256i const_5 = {0x0000000400000004, 0x0000000400000004, + 0x0000000400000004, 0x0000000400000004}; + __m256i const_6 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + __m256i const_7 = {0x000C000C000C000C, 0X000C000C000C000C, + 0xFFF4000CFFF4000C, 0xFFF4000CFFF4000C}; + __m256i const_8 = {0x0006001000060010, 0x0006001000060010, + 0xFFF00006FFF00006, 0xFFF00006FFF00006}; + __m256i const_9 = {0x0009001000090010, 0x0009001000090010, + 0x0004000F0004000F, 0x0004000F0004000F}; + __m256i const_10 = {0xFFF0000FFFF0000F, 0xFFF0000FFFF0000F, + 0xFFF7FFFCFFF7FFFC, 0xFFF7FFFCFFF7FFFC}; + __m256i const_11 = {0x0004000900040009, 0x0004000900040009, + 0x000FFFF0000FFFF0, 0x000FFFF0000FFFF0}; + __m256i const_12 = {0x000F0004000F0004, 0x000F0004000F0004, + 0xFFF0FFF7FFF0FFF7, 0xFFF0FFF7FFF0FFF7}; + __m256i shift = {0x0000000400000000, 0x0000000600000002, + 0x0000000500000001, 0x0000000700000003}; + + /* first loops */ + DUP4_ARG2(__lasx_xvld, block, 0, block, 32, block, 64, block, 96, + in0, in1, in2, in3); + in0 = __lasx_xvilvl_d(in1, in0); + in1 = __lasx_xvilvl_d(in3, in2); + temp0 = __lasx_xvpickev_h(in1, in0); + temp1 = __lasx_xvpickod_h(in1, in0); + temp0 = __lasx_xvperm_w(temp0, shift); + temp1 = __lasx_xvperm_w(temp1, shift); + + DUP2_ARG3(__lasx_xvdp2add_w_h, const_5, temp0, const_1, const_5, temp0, + const_2, t1, t2); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_3, temp1, const_4, t3, t4); + + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvsub_w(t2, t4); + temp2 = __lasx_xvadd_w(t2, t4); + temp3 = __lasx_xvsub_w(t1, t3); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 3, temp1, 3, temp2, 3, temp3, 3, + temp0, temp1, temp2, temp3); + + /* second loops */ + t1 = __lasx_xvpickev_w(temp1, temp0); + t2 = __lasx_xvpickev_w(temp3, temp2); + t1 = __lasx_xvpickev_h(t2, t1); + t3 = __lasx_xvpickod_w(temp1, temp0); + t4 = __lasx_xvpickod_w(temp3, temp2); + temp1 = __lasx_xvpickev_h(t4, t3); + temp2 = __lasx_xvpermi_q(t1, t1, 0x00); + temp3 = __lasx_xvpermi_q(t1, t1, 0x11); + t1 = __lasx_xvdp2add_w_h(const_6, temp2, const_7); + t2 = __lasx_xvdp2_w_h(temp3, const_8); + t3 = __lasx_xvadd_w(t1, t2); + t4 = __lasx_xvsub_w(t1, t2); + t4 = __lasx_xvpermi_d(t4, 0x4E); + + DUP4_ARG2(__lasx_xvdp2_w_h, temp1, const_9, temp1, const_10, temp1, + const_11, temp1, const_12, t1, t2, temp2, temp3); + + temp0 = __lasx_xvpermi_q(t2, t1, 0x20); + temp1 = __lasx_xvpermi_q(t2, t1, 0x31); + t1 = __lasx_xvadd_w(temp0, temp1); + temp0 = __lasx_xvpermi_q(temp3, temp2, 0x20); + temp1 = __lasx_xvpermi_q(temp3, temp2, 0x31); + t2 = __lasx_xvadd_w(temp1, temp0); + temp0 = __lasx_xvadd_w(t1, t3); + temp1 = __lasx_xvadd_w(t2, t4); + temp2 = __lasx_xvsub_w(t4, t2); + temp3 = __lasx_xvsub_w(t3, t1); + temp2 = __lasx_xvaddi_wu(temp2, 1); + temp3 = __lasx_xvaddi_wu(temp3, 1); + DUP4_ARG2(__lasx_xvsrai_w, temp0, 7, temp1, 7, temp2, 7, temp3, 7, + temp0, temp1, temp2, temp3); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dest + stride, 0, dest + stride2, 0, + dest + stride3, 0, const_1, const_2, const_3, const_4); + DUP4_ARG2(__lasx_xvldrepl_w, dst, 0, dst + stride, 0, dst + stride2, 0, + dst + stride3, 0, const_5, const_6, const_7, const_8); + + DUP4_ARG2(__lasx_xvilvl_w, const_2, const_1, const_4, const_3, const_5, + const_6, const_7, const_8, const_1, const_2, const_3, const_4); + DUP4_ARG1(__lasx_vext2xv_wu_bu, const_1, const_2, const_3, const_4, + const_1, const_2, const_3, const_4); + DUP4_ARG2(__lasx_xvadd_w, temp0, const_1, temp1, const_2, temp2, const_3, + temp3, const_4, temp0, temp1, temp2, temp3); + DUP4_ARG1(__lasx_xvclip255_w, temp0, temp1, temp2, temp3, + temp0, temp1, temp2, temp3); + DUP2_ARG2(__lasx_xvpickev_h, temp1, temp0, temp3, temp2, temp0, temp1); + temp0 = __lasx_xvpickev_b(temp1, temp0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dest + stride, 0, 4); + __lasx_xvstelm_w(temp0, dest + stride2, 0, 1); + __lasx_xvstelm_w(temp0, dest + stride3, 0, 5); + __lasx_xvstelm_w(temp0, dst, 0, 6); + __lasx_xvstelm_w(temp0, dst + stride, 0, 2); + __lasx_xvstelm_w(temp0, dst + stride2, 0, 7); + __lasx_xvstelm_w(temp0, dst + stride3, 0, 3); +} + +void ff_vc1_inv_trans_4x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, + int16_t *block) +{ + int dc = block[0]; + uint8_t *dst1 = dest + stride; + uint8_t *dst2 = dst1 + stride; + uint8_t *dst3 = dst2 + stride; + __m256i in0, in1, in2, in3, temp0, temp1, const_dc; + __m256i zero = {0}; + + dc = (17 * dc + 4) >> 3; + dc = (17 * dc + 64) >> 7; + const_dc = __lasx_xvreplgr2vr_h(dc); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dst1, 0, dst2, 0, dst3, 0, + in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_w, in1, in0, in3, in2, temp0, temp1); + in0 = __lasx_xvpermi_q(temp1, temp0, 0x20); + temp0 = __lasx_xvilvl_b(zero, in0); + in0 = __lasx_xvadd_h(temp0, const_dc); + temp0 = __lasx_xvssrarni_bu_h(in0, in0, 0); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dst1, 0, 1); + __lasx_xvstelm_w(temp0, dst2, 0, 4); + __lasx_xvstelm_w(temp0, dst3, 0, 5); +} + +void ff_vc1_inv_trans_4x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block) +{ + uint8_t *dst1 = dest + stride; + uint8_t *dst2 = dst1 + stride; + uint8_t *dst3 = dst2 + stride; + __m256i in0, in1, in2, in3; + __m256i temp0, temp1, temp2, temp3, t1, t2; + + __m256i const_1 = {0x0011001100110011, 0xFFEF0011FFEF0011, + 0x0011001100110011, 0xFFEF0011FFEF0011}; + __m256i const_2 = {0x000A0016000A0016, 0x0016FFF60016FFF6, + 0x000A0016000A0016, 0x0016FFF60016FFF6}; + __m256i const_64 = {0x0000004000000040, 0x0000004000000040, + 0x0000004000000040, 0x0000004000000040}; + + DUP2_ARG2(__lasx_xvld, block, 0, block, 32, in0, in1); + /* first loops */ + temp0 = __lasx_xvilvl_d(in1, in0); + temp1 = __lasx_xvpickev_h(temp0, temp0); + temp2 = __lasx_xvpickod_h(temp0, temp0); + DUP2_ARG2(__lasx_xvdp2_w_h, temp1, const_1, temp2, const_2, t1, t2); + t1 = __lasx_xvaddi_wu(t1, 4); + in0 = __lasx_xvadd_w(t1, t2); + in1 = __lasx_xvsub_w(t1, t2); + DUP2_ARG2(__lasx_xvsrai_w, in0, 3, in1, 3, in0, in1); + /* second loops */ + temp0 = __lasx_xvpickev_h(in1, in0); + temp1 = __lasx_xvpermi_q(temp0, temp0, 0x00); + temp2 = __lasx_xvpermi_q(temp0, temp0, 0x11); + const_1 = __lasx_xvpermi_d(const_1, 0xD8); + const_2 = __lasx_xvpermi_d(const_2, 0xD8); + t1 = __lasx_xvdp2add_w_h(const_64, temp1, const_1); + t2 = __lasx_xvdp2_w_h(temp2, const_2); + in0 = __lasx_xvadd_w(t1, t2); + in1 = __lasx_xvsub_w(t1, t2); + DUP2_ARG2(__lasx_xvsrai_w, in0, 7, in1, 7, in0, in1); + temp0 = __lasx_xvshuf4i_w(in0, 0x9C); + temp1 = __lasx_xvshuf4i_w(in1, 0x9C); + + DUP4_ARG2(__lasx_xvldrepl_w, dest, 0, dst1, 0, dst2, 0, dst3, 0, + in0, in1, in2, in3); + temp2 = __lasx_xvilvl_w(in2, in0); + temp2 = __lasx_vext2xv_wu_bu(temp2); + temp3 = __lasx_xvilvl_w(in1, in3); + temp3 = __lasx_vext2xv_wu_bu(temp3); + temp0 = __lasx_xvadd_w(temp0, temp2); + temp1 = __lasx_xvadd_w(temp1, temp3); + DUP2_ARG1(__lasx_xvclip255_w, temp0, temp1, temp0, temp1); + temp1 = __lasx_xvpickev_h(temp1, temp0); + temp0 = __lasx_xvpickev_b(temp1, temp1); + __lasx_xvstelm_w(temp0, dest, 0, 0); + __lasx_xvstelm_w(temp0, dst1, 0, 5); + __lasx_xvstelm_w(temp0, dst2, 0, 4); + __lasx_xvstelm_w(temp0, dst3, 0, 1); +} + +static void put_vc1_mspel_mc_h_v_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int hmode, int vmode, + int rnd) +{ + __m256i in0, in1, in2, in3; + __m256i t0, t1, t2, t3, t4, t5, t6, t7; + __m256i temp0, temp1, const_para1_2, const_para0_3; + __m256i const_r, const_sh; + __m256i sh = {0x0000000400000000, 0x0000000500000001, + 0x0000000600000002, 0x0000000700000003}; + static const uint8_t para_value[][4] = {{4, 3, 53, 18}, + {1, 1, 9, 9}, + {3, 4, 18, 53}}; + static const int shift_value[] = {0, 5, 1, 5}; + int shift = (shift_value[hmode] + shift_value[vmode]) >> 1; + int r = (1 << (shift - 1)) + rnd - 1; + const uint8_t *para_v = para_value[vmode - 1]; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride4 = stride << 2; + ptrdiff_t stride3 = stride2 + stride; + + const_r = __lasx_xvreplgr2vr_h(r); + const_sh = __lasx_xvreplgr2vr_h(shift); + src -= 1, src -= stride; + const_para0_3 = __lasx_xvldrepl_h(para_v, 0); + const_para1_2 = __lasx_xvldrepl_h(para_v, 2); + DUP4_ARG2(__lasx_xvld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, in0, in1, in2, in3); + DUP4_ARG2(__lasx_xvpermi_d, in0, 0xD8, in1, 0xD8, in2, 0xD8, in3, 0xD8, + in0, in1, in2, in3); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t0 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_h_bu(t0, temp1, const_para0_3); + src += stride4; + in0 = __lasx_xvld(src, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in3, in2, in0, in1, temp0, temp1); + t1 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t1 = __lasx_xvdp2sub_h_bu(t1, temp1, const_para0_3); + src += stride; + in1 = __lasx_xvld(src, 0); + in1 = __lasx_xvpermi_d(in1, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in0, in3, in1, in2, temp0, temp1); + t2 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t2 = __lasx_xvdp2sub_h_bu(t2, temp1, const_para0_3); + src += stride; + in2 = __lasx_xvld(src, 0); + in2 = __lasx_xvpermi_d(in2, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in1, in0, in2, in3, temp0, temp1); + t3 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t3 = __lasx_xvdp2sub_h_bu(t3, temp1, const_para0_3); + src += stride; + in3 = __lasx_xvld(src, 0); + in3 = __lasx_xvpermi_d(in3, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t4 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t4 = __lasx_xvdp2sub_h_bu(t4, temp1, const_para0_3); + src += stride; + in0 = __lasx_xvld(src, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in3, in2, in0, in1, temp0, temp1); + t5 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t5 = __lasx_xvdp2sub_h_bu(t5, temp1, const_para0_3); + src += stride; + in1 = __lasx_xvld(src, 0); + in1 = __lasx_xvpermi_d(in1, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in0, in3, in1, in2, temp0, temp1); + t6 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t6 = __lasx_xvdp2sub_h_bu(t6, temp1, const_para0_3); + src += stride; + in2 = __lasx_xvld(src, 0); + in2 = __lasx_xvpermi_d(in2, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in1, in0, in2, in3, temp0, temp1); + t7 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t7 = __lasx_xvdp2sub_h_bu(t7, temp1, const_para0_3); + DUP4_ARG2(__lasx_xvadd_h, t0, const_r, t1, const_r, t2, const_r, t3, + const_r, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvadd_h, t4, const_r, t5, const_r, t6, const_r, t7, + const_r, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvsra_h, t0, const_sh, t1, const_sh, t2, const_sh, + t3, const_sh, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvsra_h, t4, const_sh, t5, const_sh, t6, const_sh, + t7, const_sh, t4, t5, t6, t7); + LASX_TRANSPOSE8x8_H(t0, t1, t2, t3, t4, t5, t6, t7, t0, + t1, t2, t3, t4, t5, t6, t7); + para_v = para_value[hmode - 1]; + const_para0_3 = __lasx_xvldrepl_h(para_v, 0); + const_para1_2 = __lasx_xvldrepl_h(para_v, 2); + const_para0_3 = __lasx_vext2xv_h_b(const_para0_3); + const_para1_2 = __lasx_vext2xv_h_b(const_para1_2); + r = 64 - rnd; + const_r = __lasx_xvreplgr2vr_w(r); + DUP4_ARG2(__lasx_xvpermi_d, t0, 0x72, t1, 0x72, t2, 0x72, t0, 0xD8, + in0, in1, in2, t0); + DUP4_ARG2(__lasx_xvpermi_d, t1, 0xD8, t2, 0xD8, t3, 0xD8, t4, 0xD8, + t1, t2, t3, t4); + DUP2_ARG2(__lasx_xvpermi_d, t5, 0xD8, t6, 0xD8, t5, t6); + t7 = __lasx_xvpermi_d(t7, 0xD8); + DUP2_ARG2(__lasx_xvilvl_h, t2, t1, t3, t0, temp0, temp1); + t0 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_w_h(t0, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t3, t2, t4, t1, temp0, temp1); + t1 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t1 = __lasx_xvdp2sub_w_h(t1, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t4, t3, t5, t2, temp0, temp1); + t2 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t2 = __lasx_xvdp2sub_w_h(t2, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t5, t4, t6, t3, temp0, temp1); + t3 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t3 = __lasx_xvdp2sub_w_h(t3, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t6, t5, t7, t4, temp0, temp1); + t4 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t4 = __lasx_xvdp2sub_w_h(t4, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, t7, t6, in0, t5, temp0, temp1); + t5 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t5 = __lasx_xvdp2sub_w_h(t5, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, in0, t7, in1, t6, temp0, temp1); + t6 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t6 = __lasx_xvdp2sub_w_h(t6, temp1, const_para0_3); + DUP2_ARG2(__lasx_xvilvl_h, in1, in0, in2, t7, temp0, temp1); + t7 = __lasx_xvdp2_w_h(temp0, const_para1_2); + t7 = __lasx_xvdp2sub_w_h(t7, temp1, const_para0_3); + DUP4_ARG2(__lasx_xvadd_w, t0, const_r, t1, const_r, t2, const_r, + t3, const_r, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvadd_w, t4, const_r, t5, const_r, t6, const_r, + t7, const_r, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvsrai_w, t0, 7, t1, 7, t2, 7, t3, 7, t0, t1, t2, t3); + DUP4_ARG2(__lasx_xvsrai_w, t4, 7, t5, 7, t6, 7, t7, 7, t4, t5, t6, t7); + LASX_TRANSPOSE8x8_W(t0, t1, t2, t3, t4, t5, t6, t7, + t0, t1, t2, t3, t4, t5, t6, t7); + DUP4_ARG1(__lasx_xvclip255_w, t0, t1, t2, t3, t0, t1, t2, t3); + DUP4_ARG1(__lasx_xvclip255_w, t4, t5, t6, t7, t4, t5, t6, t7); + DUP4_ARG2(__lasx_xvpickev_h, t1, t0, t3, t2, t5, t4, t7, t6, + t0, t1, t2, t3); + DUP2_ARG2(__lasx_xvpickev_b, t1, t0, t3, t2, t0, t1); + t0 = __lasx_xvperm_w(t0, sh); + t1 = __lasx_xvperm_w(t1, sh); + __lasx_xvstelm_d(t0, dst, 0, 0); + __lasx_xvstelm_d(t0, dst + stride, 0, 1); + __lasx_xvstelm_d(t0, dst + stride2, 0, 2); + __lasx_xvstelm_d(t0, dst + stride3, 0, 3); + dst += stride4; + __lasx_xvstelm_d(t1, dst, 0, 0); + __lasx_xvstelm_d(t1, dst + stride, 0, 1); + __lasx_xvstelm_d(t1, dst + stride2, 0, 2); + __lasx_xvstelm_d(t1, dst + stride3, 0, 3); +} + +#define PUT_VC1_MSPEL_MC_LASX(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ +} \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_lasx(dst + 8, src + 8, stride, hmode, vmode, rnd); \ + dst += 8 * stride, src += 8 * stride; \ + put_vc1_mspel_mc_h_v_lasx(dst, src, stride, hmode, vmode, rnd); \ + put_vc1_mspel_mc_h_v_lasx(dst + 8, src + 8, stride, hmode, vmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_LASX(1, 1); +PUT_VC1_MSPEL_MC_LASX(1, 2); +PUT_VC1_MSPEL_MC_LASX(1, 3); + +PUT_VC1_MSPEL_MC_LASX(2, 1); +PUT_VC1_MSPEL_MC_LASX(2, 2); +PUT_VC1_MSPEL_MC_LASX(2, 3); + +PUT_VC1_MSPEL_MC_LASX(3, 1); +PUT_VC1_MSPEL_MC_LASX(3, 2); +PUT_VC1_MSPEL_MC_LASX(3, 3); + +void ff_put_no_rnd_vc1_chroma_mc8_lasx(uint8_t *dst /* align 8 */, + uint8_t *src /* align 1 */, + ptrdiff_t stride, int h, int x, int y) +{ + const int intA = (8 - x) * (8 - y); + const int intB = (x) * (8 - y); + const int intC = (8 - x) * (y); + const int intD = (x) * (y); + __m256i src00, src01, src10, src11; + __m256i A, B, C, D; + int i; + + av_assert2(x < 8 && y < 8 && x >= 0 && y >= 0); + + A = __lasx_xvreplgr2vr_h(intA); + B = __lasx_xvreplgr2vr_h(intB); + C = __lasx_xvreplgr2vr_h(intC); + D = __lasx_xvreplgr2vr_h(intD); + for(i = 0; i < h; i++){ + DUP2_ARG2(__lasx_xvld, src, 0, src, 1, src00, src01); + src += stride; + DUP2_ARG2(__lasx_xvld, src, 0, src, 1, src10, src11); + + DUP4_ARG1(__lasx_vext2xv_hu_bu, src00, src01, src10, src11, + src00, src01, src10, src11); + DUP4_ARG2(__lasx_xvmul_h, src00, A, src01, B, src10, C, src11, D, + src00, src01, src10, src11); + src00 = __lasx_xvadd_h(src00, src01); + src10 = __lasx_xvadd_h(src10, src11); + src00 = __lasx_xvadd_h(src00, src10); + src00 = __lasx_xvaddi_hu(src00, 28); + src00 = __lasx_xvsrli_h(src00, 6); + src00 = __lasx_xvpickev_b(src00, src00); + __lasx_xvstelm_d(src00, dst, 0, 0); + dst += stride; + } +} + +static void put_vc1_mspel_mc_v_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int vmode, int rnd) +{ + __m256i in0, in1, in2, in3, temp0, temp1, t0; + __m256i const_para0_3, const_para1_2, const_r, const_sh; + static const uint16_t para_value[][2] = {{0x0304, 0x1235}, + {0x0101, 0x0909}, + {0x0403, 0x3512}}; + const uint16_t *para_v = para_value[vmode - 1]; + static const int shift_value[] = {0, 6, 4, 6}; + static int add_value[3]; + ptrdiff_t stride_2x = stride << 1; + int i = 0; + add_value[2] = add_value[0] = 31 + rnd, add_value[1] = 7 + rnd; + + const_r = __lasx_xvreplgr2vr_h(add_value[vmode - 1]); + const_sh = __lasx_xvreplgr2vr_h(shift_value[vmode]); + const_para0_3 = __lasx_xvreplgr2vr_h(*para_v); + const_para1_2 = __lasx_xvreplgr2vr_h(*(para_v + 1)); + + DUP2_ARG2(__lasx_xvld, src - stride, 0, src, 0, in0, in1); + in2 = __lasx_xvld(src + stride, 0); + in0 = __lasx_xvpermi_d(in0, 0xD8); + in1 = __lasx_xvpermi_d(in1, 0xD8); + in2 = __lasx_xvpermi_d(in2, 0xD8); + for (; i < 16; i++) { + in3 = __lasx_xvld(src + stride_2x, 0); + in3 = __lasx_xvpermi_d(in3, 0xD8); + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, temp0, temp1); + t0 = __lasx_xvdp2_h_bu(temp0, const_para1_2); + t0 = __lasx_xvdp2sub_h_bu(t0, temp1, const_para0_3); + t0 = __lasx_xvadd_h(t0, const_r); + t0 = __lasx_xvsra_h(t0, const_sh); + t0 = __lasx_xvclip255_h(t0); + t0 = __lasx_xvpickev_b(t0, t0); + __lasx_xvstelm_d(t0, dst, 0, 0); + __lasx_xvstelm_d(t0, dst, 8, 2); + dst += stride; + src += stride; + in0 = in1; + in1 = in2; + in2 = in3; + } +} + +#define PUT_VC1_MSPEL_MC_V_LASX(vmode) \ +void ff_put_vc1_mspel_mc0 ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_v_lasx(dst, src, stride, vmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_V_LASX(1); +PUT_VC1_MSPEL_MC_V_LASX(2); +PUT_VC1_MSPEL_MC_V_LASX(3); + +#define ROW_LASX(in0, in1, in2, in3, out0) \ + DUP2_ARG2(__lasx_xvilvl_b, in2, in1, in3, in0, tmp0_m, tmp1_m); \ + out0 = __lasx_xvdp2_h_bu(tmp0_m, const_para1_2); \ + out0 = __lasx_xvdp2sub_h_bu(out0, tmp1_m, const_para0_3); \ + out0 = __lasx_xvadd_h(out0, const_r); \ + out0 = __lasx_xvsra_h(out0, const_sh); \ + out0 = __lasx_xvclip255_h(out0); \ + out0 = __lasx_xvpickev_b(out0, out0); \ + out0 = __lasx_xvpermi_d(out0, 0xd8); \ + +static void put_vc1_mspel_mc_h_lasx(uint8_t *dst, const uint8_t *src, + ptrdiff_t stride, int hmode, int rnd) +{ + __m256i in0, in1, in2, in3, in4, in5, in6, in7, + in8, in9, in10, in11, in12, in13, in14, in15; + __m256i out0, out1, out2, out3, out4, out5, out6, out7, out8, out9, + out10, out11, out12, out13, out14, out15, out16, out17, out18; + __m256i const_para0_3, const_para1_2, const_r, const_sh; + __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; + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride4 = stride << 2; + ptrdiff_t stride3 = stride2 + stride; + static const uint16_t para_value[][2] = {{0x0304, 0x1235}, + {0x0101, 0x0909}, + {0x0403, 0x3512}}; + const uint16_t *para_v = para_value[hmode - 1]; + static const int shift_value[] = {0, 6, 4, 6}; + static int add_value[3]; + uint8_t *_src = (uint8_t*)src - 1; + add_value[2] = add_value[0] = 32 - rnd, add_value[1] = 8 - rnd; + + const_r = __lasx_xvreplgr2vr_h(add_value[hmode - 1]); + const_sh = __lasx_xvreplgr2vr_h(shift_value[hmode]); + const_para0_3 = __lasx_xvreplgr2vr_h(*para_v); + const_para1_2 = __lasx_xvreplgr2vr_h(*(para_v + 1)); + + in0 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in1, in2); + in3 = __lasx_xvldx(_src, stride3); + _src += stride4; + in4 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in5, in6); + in7 = __lasx_xvldx(_src, stride3); + _src += stride4; + in8 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in9, in10); + in11 = __lasx_xvldx(_src, stride3); + _src += stride4; + in12 = __lasx_xvld(_src, 0); + DUP2_ARG2(__lasx_xvldx, _src, stride, _src, stride2, in13, in14); + in15 = __lasx_xvldx(_src, stride3); + DUP4_ARG2(__lasx_xvilvl_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvl_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out0, out2, out4, out6); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out1, out3, out5, out7); + + DUP4_ARG2(__lasx_xvilvh_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvh_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out8, out10, out12, out14); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out9, out11, out13, out15); + DUP2_ARG3(__lasx_xvpermi_q, out0, out0, 0x31, out1, out1, 0x31, out16, out17); + out18 = __lasx_xvpermi_q(out2, out2, 0x31); + + DUP4_ARG2(__lasx_xvpermi_d, out0, 0xD8, out1, 0xD8, out2, 0xD8, out3, 0xD8, + out0, out1, out2, out3); + DUP4_ARG2(__lasx_xvpermi_d, out4, 0xD8, out5, 0xD8, out6, 0xD8, out7, 0xD8, + out4, out5, out6, out7); + DUP4_ARG2(__lasx_xvpermi_d, out8, 0xD8, out9, 0xD8, out10, 0xD8, out11, + 0xD8, out8, out9, out10, out11); + DUP4_ARG2(__lasx_xvpermi_d, out12, 0xD8, out13, 0xD8, out14, 0xD8, out15, + 0xD8, out12, out13, out14, out15); + out16 = __lasx_xvpermi_d(out16, 0xD8); + out17 = __lasx_xvpermi_d(out17, 0xD8); + out18 = __lasx_xvpermi_d(out18, 0xD8); + + ROW_LASX(out0, out1, out2, out3, in0); + ROW_LASX(out1, out2, out3, out4, in1); + ROW_LASX(out2, out3, out4, out5, in2); + ROW_LASX(out3, out4, out5, out6, in3); + ROW_LASX(out4, out5, out6, out7, in4); + ROW_LASX(out5, out6, out7, out8, in5); + ROW_LASX(out6, out7, out8, out9, in6); + ROW_LASX(out7, out8, out9, out10, in7); + ROW_LASX(out8, out9, out10, out11, in8); + ROW_LASX(out9, out10, out11, out12, in9); + ROW_LASX(out10, out11, out12, out13, in10); + ROW_LASX(out11, out12, out13, out14, in11); + ROW_LASX(out12, out13, out14, out15, in12); + ROW_LASX(out13, out14, out15, out16, in13); + ROW_LASX(out14, out15, out16, out17, in14); + ROW_LASX(out15, out16, out17, out18, in15); + + DUP4_ARG2(__lasx_xvilvl_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvl_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out0, out2, out4, out6); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out1, out3, out5, out7); + + DUP4_ARG2(__lasx_xvilvh_b, in2, in0, in3, in1, in6, in4, in7, in5, + tmp0_m, tmp1_m, tmp2_m, tmp3_m); + DUP4_ARG2(__lasx_xvilvh_b, in10, in8, in11, in9, in14, in12, in15, in13, + tmp4_m, tmp5_m, tmp6_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t0, t2, t4, t6); + DUP4_ARG2(__lasx_xvilvh_b, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, t1, t3, t5, t7); + DUP4_ARG2(__lasx_xvilvl_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp0_m, tmp4_m, + tmp1_m, tmp5_m); + DUP4_ARG2(__lasx_xvilvh_w, t2, t0, t3, t1, t6, t4, t7, t5, tmp2_m, tmp6_m, + tmp3_m, tmp7_m); + DUP4_ARG2(__lasx_xvilvl_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out8, out10, out12, out14); + DUP4_ARG2(__lasx_xvilvh_d, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tmp5_m, tmp4_m, + tmp7_m, tmp6_m, out9, out11, out13, out15); + __lasx_xvstelm_d(out0, dst, 0, 0); + __lasx_xvstelm_d(out0, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out1, dst, 0, 0); + __lasx_xvstelm_d(out1, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out2, dst, 0, 0); + __lasx_xvstelm_d(out2, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out3, dst, 0, 0); + __lasx_xvstelm_d(out3, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out4, dst, 0, 0); + __lasx_xvstelm_d(out4, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out5, dst, 0, 0); + __lasx_xvstelm_d(out5, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out6, dst, 0, 0); + __lasx_xvstelm_d(out6, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out7, dst, 0, 0); + __lasx_xvstelm_d(out7, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out8, dst, 0, 0); + __lasx_xvstelm_d(out8, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out9, dst, 0, 0); + __lasx_xvstelm_d(out9, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out10, dst, 0, 0); + __lasx_xvstelm_d(out10, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out11, dst, 0, 0); + __lasx_xvstelm_d(out11, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out12, dst, 0, 0); + __lasx_xvstelm_d(out12, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out13, dst, 0, 0); + __lasx_xvstelm_d(out13, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out14, dst, 0, 0); + __lasx_xvstelm_d(out14, dst, 8, 1); + dst += stride; + __lasx_xvstelm_d(out15, dst, 0, 0); + __lasx_xvstelm_d(out15, dst, 8, 1); +} + +#define PUT_VC1_MSPEL_MC_H_LASX(hmode) \ +void ff_put_vc1_mspel_mc ## hmode ## 0_16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd) \ +{ \ + put_vc1_mspel_mc_h_lasx(dst, src, stride, hmode, rnd); \ +} + +PUT_VC1_MSPEL_MC_H_LASX(1); +PUT_VC1_MSPEL_MC_H_LASX(2); +PUT_VC1_MSPEL_MC_H_LASX(3); diff --git a/libavcodec/loongarch/vc1dsp_loongarch.h b/libavcodec/loongarch/vc1dsp_loongarch.h new file mode 100644 index 0000000000..398631aecc --- /dev/null +++ b/libavcodec/loongarch/vc1dsp_loongarch.h @@ -0,0 +1,79 @@ +/* + * 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_VC1DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VC1DSP_LOONGARCH_H + +#include "libavcodec/vc1dsp.h" +#include "libavutil/avassert.h" + +void ff_vc1_inv_trans_8x8_lasx(int16_t block[64]); +void ff_vc1_inv_trans_8x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_8x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_8x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x8_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *blokc); +void ff_vc1_inv_trans_4x4_dc_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); +void ff_vc1_inv_trans_4x4_lasx(uint8_t *dest, ptrdiff_t stride, int16_t *block); + +#define FF_PUT_VC1_MSPEL_MC_LASX(hmode, vmode) \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); \ +void ff_put_vc1_mspel_mc ## hmode ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_LASX(1, 1); +FF_PUT_VC1_MSPEL_MC_LASX(1, 2); +FF_PUT_VC1_MSPEL_MC_LASX(1, 3); + +FF_PUT_VC1_MSPEL_MC_LASX(2, 1); +FF_PUT_VC1_MSPEL_MC_LASX(2, 2); +FF_PUT_VC1_MSPEL_MC_LASX(2, 3); + +FF_PUT_VC1_MSPEL_MC_LASX(3, 1); +FF_PUT_VC1_MSPEL_MC_LASX(3, 2); +FF_PUT_VC1_MSPEL_MC_LASX(3, 3); + +#define FF_PUT_VC1_MSPEL_MC_V_LASX(vmode) \ +void ff_put_vc1_mspel_mc0 ## vmode ## _16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_V_LASX(1); +FF_PUT_VC1_MSPEL_MC_V_LASX(2); +FF_PUT_VC1_MSPEL_MC_V_LASX(3); + +#define FF_PUT_VC1_MSPEL_MC_H_LASX(hmode) \ +void ff_put_vc1_mspel_mc ## hmode ## 0_16_lasx(uint8_t *dst, \ + const uint8_t *src, \ + ptrdiff_t stride, int rnd); + +FF_PUT_VC1_MSPEL_MC_H_LASX(1); +FF_PUT_VC1_MSPEL_MC_H_LASX(2); +FF_PUT_VC1_MSPEL_MC_H_LASX(3); + +void ff_put_no_rnd_vc1_chroma_mc8_lasx(uint8_t *dst /* align 8 */, + uint8_t *src /* align 1 */, + ptrdiff_t stride, int h, int x, int y); + +#endif /* AVCODEC_LOONGARCH_VC1DSP_LOONGARCH_H */ diff --git a/libavcodec/loongarch/videodsp_init.c b/libavcodec/loongarch/videodsp_init.c new file mode 100644 index 0000000000..6cbb7763ff --- /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/loongarch/vp8_lpf_lsx.c b/libavcodec/loongarch/vp8_lpf_lsx.c new file mode 100644 index 0000000000..f0fc3f3a5b --- /dev/null +++ b/libavcodec/loongarch/vp8_lpf_lsx.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/vp8dsp.h" +#include "vp8dsp_loongarch.h" +#include "libavutil/loongarch/loongson_intrinsics.h" + +#define VP8_LPF_FILTER4_4W(p1_in_out, p0_in_out, q0_in_out, q1_in_out, \ + mask_in, hev_in) \ +{ \ + __m128i p1_m, p0_m, q0_m, q1_m, q0_sub_p0, filt_sign; \ + __m128i filt, filt1, filt2, cnst4b, cnst3b; \ + __m128i q0_sub_p0_l, q0_sub_p0_h, filt_h, filt_l, cnst3h; \ + \ + p1_m = __lsx_vxori_b(p1_in_out, 0x80); \ + p0_m = __lsx_vxori_b(p0_in_out, 0x80); \ + q0_m = __lsx_vxori_b(q0_in_out, 0x80); \ + q1_m = __lsx_vxori_b(q1_in_out, 0x80); \ + filt = __lsx_vssub_b(p1_m, q1_m); \ + filt = filt & hev_in; \ + \ + q0_sub_p0 = __lsx_vsub_b(q0_m, p0_m); \ + filt_sign = __lsx_vslti_b(filt, 0); \ + \ + cnst3h = __lsx_vreplgr2vr_h(3); \ + q0_sub_p0_l = __lsx_vilvl_b(q0_sub_p0, q0_sub_p0); \ + q0_sub_p0_l = __lsx_vdp2_h_b(q0_sub_p0_l, cnst3h); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_l = __lsx_vadd_h(filt_l, q0_sub_p0_l); \ + filt_l = __lsx_vsat_h(filt_l, 7); \ + \ + q0_sub_p0_h = __lsx_vilvh_b(q0_sub_p0, q0_sub_p0); \ + q0_sub_p0_h = __lsx_vdp2_h_b(q0_sub_p0_h, cnst3h); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + filt_h = __lsx_vadd_h(filt_h, q0_sub_p0_h); \ + filt_h = __lsx_vsat_h(filt_h, 7); \ + \ + filt = __lsx_vpickev_b(filt_h, filt_l); \ + filt = filt & mask_in; \ + cnst4b = __lsx_vreplgr2vr_b(4); \ + filt1 = __lsx_vsadd_b(filt, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + \ + cnst3b = __lsx_vreplgr2vr_b(3); \ + filt2 = __lsx_vsadd_b(filt, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + \ + q0_m = __lsx_vssub_b(q0_m, filt1); \ + q0_in_out = __lsx_vxori_b(q0_m, 0x80); \ + p0_m = __lsx_vsadd_b(p0_m, filt2); \ + p0_in_out = __lsx_vxori_b(p0_m, 0x80); \ + \ + filt = __lsx_vsrari_b(filt1, 1); \ + hev_in = __lsx_vxori_b(hev_in, 0xff); \ + filt = filt & hev_in; \ + \ + q1_m = __lsx_vssub_b(q1_m, filt); \ + q1_in_out = __lsx_vxori_b(q1_m, 0x80); \ + p1_m = __lsx_vsadd_b(p1_m, filt); \ + p1_in_out = __lsx_vxori_b(p1_m, 0x80); \ +} + +#define VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev) \ +{ \ + __m128i p2_m, p1_m, p0_m, q2_m, q1_m, q0_m; \ + __m128i filt, q0_sub_p0, cnst4b, cnst3b; \ + __m128i u, filt1, filt2, filt_sign, q0_sub_p0_sign; \ + __m128i q0_sub_p0_l, q0_sub_p0_h, filt_l, u_l, u_h, filt_h; \ + __m128i cnst3h, cnst27h, cnst18h, cnst63h; \ + \ + cnst3h = __lsx_vreplgr2vr_h(3); \ + \ + p2_m = __lsx_vxori_b(p2, 0x80); \ + p1_m = __lsx_vxori_b(p1, 0x80); \ + p0_m = __lsx_vxori_b(p0, 0x80); \ + q0_m = __lsx_vxori_b(q0, 0x80); \ + q1_m = __lsx_vxori_b(q1, 0x80); \ + q2_m = __lsx_vxori_b(q2, 0x80); \ + \ + filt = __lsx_vssub_b(p1_m, q1_m); \ + q0_sub_p0 = __lsx_vsub_b(q0_m, p0_m); \ + q0_sub_p0_sign = __lsx_vslti_b(q0_sub_p0, 0); \ + filt_sign = __lsx_vslti_b(filt, 0); \ + \ + /* right part */ \ + q0_sub_p0_l = __lsx_vilvl_b(q0_sub_p0_sign, q0_sub_p0); \ + q0_sub_p0_l = __lsx_vmul_h(q0_sub_p0_l, cnst3h); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_l = __lsx_vadd_h(filt_l, q0_sub_p0_l); \ + filt_l = __lsx_vsat_h(filt_l, 7); \ + \ + /* left part */ \ + q0_sub_p0_h = __lsx_vilvh_b(q0_sub_p0_sign, q0_sub_p0); \ + q0_sub_p0_h = __lsx_vmul_h(q0_sub_p0_h, cnst3h); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + filt_h = __lsx_vadd_h(filt_h, q0_sub_p0_h); \ + filt_h = __lsx_vsat_h(filt_h, 7); \ + \ + /* combine left and right part */ \ + filt = __lsx_vpickev_b(filt_h, filt_l); \ + filt = filt & mask; \ + filt2 = filt & hev; \ + /* filt_val &= ~hev */ \ + hev = __lsx_vxori_b(hev, 0xff); \ + filt = filt & hev; \ + cnst4b = __lsx_vreplgr2vr_b(4); \ + filt1 = __lsx_vsadd_b(filt2, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + cnst3b = __lsx_vreplgr2vr_b(3); \ + filt2 = __lsx_vsadd_b(filt2, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + q0_m = __lsx_vssub_b(q0_m, filt1); \ + p0_m = __lsx_vsadd_b(p0_m, filt2); \ + \ + filt_sign = __lsx_vslti_b(filt, 0); \ + filt_l = __lsx_vilvl_b(filt_sign, filt); \ + filt_h = __lsx_vilvh_b(filt_sign, filt); \ + \ + cnst27h = __lsx_vreplgr2vr_h(27); \ + cnst63h = __lsx_vreplgr2vr_h(63); \ + \ + /* right part */ \ + u_l = __lsx_vmul_h(filt_l, cnst27h); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + /* left part */ \ + u_h = __lsx_vmul_h(filt_h, cnst27h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q0_m = __lsx_vssub_b(q0_m, u); \ + q0 = __lsx_vxori_b(q0_m, 0x80); \ + p0_m = __lsx_vsadd_b(p0_m, u); \ + p0 = __lsx_vxori_b(p0_m, 0x80); \ + cnst18h = __lsx_vreplgr2vr_h(18); \ + u_l = __lsx_vmul_h(filt_l, cnst18h); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + \ + /* left part */ \ + u_h = __lsx_vmul_h(filt_h, cnst18h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q1_m = __lsx_vssub_b(q1_m, u); \ + q1 = __lsx_vxori_b(q1_m, 0x80); \ + p1_m = __lsx_vsadd_b(p1_m, u); \ + p1 = __lsx_vxori_b(p1_m, 0x80); \ + u_l = __lsx_vslli_h(filt_l, 3); \ + u_l = __lsx_vadd_h(u_l, filt_l); \ + u_l = __lsx_vadd_h(u_l, cnst63h); \ + u_l = __lsx_vsrai_h(u_l, 7); \ + u_l = __lsx_vsat_h(u_l, 7); \ + \ + /* left part */ \ + u_h = __lsx_vslli_h(filt_h, 3); \ + u_h = __lsx_vadd_h(u_h, filt_h); \ + u_h = __lsx_vadd_h(u_h, cnst63h); \ + u_h = __lsx_vsrai_h(u_h, 7); \ + u_h = __lsx_vsat_h(u_h, 7); \ + /* combine left and right part */ \ + u = __lsx_vpickev_b(u_h, u_l); \ + q2_m = __lsx_vssub_b(q2_m, u); \ + q2 = __lsx_vxori_b(q2_m, 0x80); \ + p2_m = __lsx_vsadd_b(p2_m, u); \ + p2 = __lsx_vxori_b(p2_m, 0x80); \ +} + +#define LPF_MASK_HEV(p3_src, p2_src, p1_src, p0_src, \ + q0_src, q1_src, q2_src, q3_src, \ + limit_src, b_limit_src, thresh_src, \ + hev_dst, mask_dst, flat_dst) \ +{ \ + __m128i p3_asub_p2_m, p2_asub_p1_m, p1_asub_p0_m, q1_asub_q0_m; \ + __m128i p1_asub_q1_m, p0_asub_q0_m, q3_asub_q2_m, q2_asub_q1_m; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_m = __lsx_vabsd_bu(p3_src, p2_src); \ + p2_asub_p1_m = __lsx_vabsd_bu(p2_src, p1_src); \ + p1_asub_p0_m = __lsx_vabsd_bu(p1_src, p0_src); \ + q1_asub_q0_m = __lsx_vabsd_bu(q1_src, q0_src); \ + q2_asub_q1_m = __lsx_vabsd_bu(q2_src, q1_src); \ + q3_asub_q2_m = __lsx_vabsd_bu(q3_src, q2_src); \ + p0_asub_q0_m = __lsx_vabsd_bu(p0_src, q0_src); \ + p1_asub_q1_m = __lsx_vabsd_bu(p1_src, q1_src); \ + \ + /* calculation of hev */ \ + flat_dst = __lsx_vmax_bu(p1_asub_p0_m, q1_asub_q0_m); \ + hev_dst = __lsx_vslt_bu(thresh_src, flat_dst); \ + /* calculation of mask */ \ + p0_asub_q0_m = __lsx_vsadd_bu(p0_asub_q0_m, p0_asub_q0_m); \ + p1_asub_q1_m = __lsx_vsrli_b(p1_asub_q1_m, 1); \ + p0_asub_q0_m = __lsx_vsadd_bu(p0_asub_q0_m, p1_asub_q1_m); \ + mask_dst = __lsx_vslt_bu(b_limit_src, p0_asub_q0_m); \ + mask_dst = __lsx_vmax_bu(flat_dst, mask_dst); \ + p3_asub_p2_m = __lsx_vmax_bu(p3_asub_p2_m, p2_asub_p1_m); \ + mask_dst = __lsx_vmax_bu(p3_asub_p2_m, mask_dst); \ + q2_asub_q1_m = __lsx_vmax_bu(q2_asub_q1_m, q3_asub_q2_m); \ + mask_dst = __lsx_vmax_bu(q2_asub_q1_m, mask_dst); \ + mask_dst = __lsx_vslt_bu(limit_src, mask_dst); \ + mask_dst = __lsx_vxori_b(mask_dst, 0xff); \ +} + +#define VP8_ST6x1_UB(in0, in0_idx, in1, in1_idx, pdst, stride) \ +{ \ + __lsx_vstelm_w(in0, pdst, 0, in0_idx); \ + __lsx_vstelm_h(in1, pdst + stride, 0, in1_idx); \ +} + +#define ST_W4(in, idx0, idx1, idx2, idx3, pdst, stride) \ +{ \ + __lsx_vstelm_w(in, pdst, 0, idx0); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx1); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx2); \ + pdst += stride; \ + __lsx_vstelm_w(in, pdst, 0, idx3); \ + pdst += stride; \ +} + +void ff_vp8_v_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + /*load vector elements*/ + DUP4_ARG2(__lsx_vld, dst - stride4, 0, dst - stride3, 0, dst - stride2, 0, + dst - stride, 0, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst + stride, 0, dst + stride2, 0, dst + stride3, 0, + q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + /*store vector elements*/ + __lsx_vst(p2, dst - stride3, 0); + __lsx_vst(p1, dst - stride2, 0); + __lsx_vst(p0, dst - stride, 0); + __lsx_vst(q0, dst, 0); + + __lsx_vst(q1, dst + stride, 0); + __lsx_vst(q2, dst + stride2, 0); +} + +void ff_vp8_v_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i p3_u, p2_u, p1_u, p0_u, q3_u, q2_u, q1_u, q0_u; + __m128i p3_v, p2_v, p1_v, p0_v, q3_v, q2_v, q1_v, q0_v; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + DUP4_ARG2(__lsx_vld, dst_u - stride4, 0, dst_u - stride3, 0, dst_u - stride2, 0, + dst_u - stride, 0, p3_u, p2_u, p1_u, p0_u); + DUP4_ARG2(__lsx_vld, dst_u, 0, dst_u + stride, 0, dst_u + stride2, 0, + dst_u + stride3, 0, q0_u, q1_u, q2_u, q3_u); + + DUP4_ARG2(__lsx_vld, dst_v - stride4, 0, dst_v - stride3, 0, dst_v - stride2, 0, + dst_v - stride, 0, p3_v, p2_v, p1_v, p0_v); + DUP4_ARG2(__lsx_vld, dst_v, 0, dst_v + stride, 0, dst_v + stride2, 0, + dst_v + stride3, 0, q0_v, q1_v, q2_v, q3_v); + + /* rht 8 element of p3 are u pixel and left 8 element of p3 are v pixei */ + DUP4_ARG2(__lsx_vilvl_d, p3_v, p3_u, p2_v, p2_u, p1_v, p1_u, p0_v, p0_u, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vilvl_d, q0_v, q0_u, q1_v, q1_u, q2_v, q2_u, q3_v, q3_u, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + __lsx_vstelm_d(p2, dst_u - stride3, 0, 0); + __lsx_vstelm_d(p1, dst_u - stride2, 0, 0); + __lsx_vstelm_d(p0, dst_u - stride , 0, 0); + __lsx_vstelm_d(q0, dst_u, 0, 0); + + __lsx_vstelm_d(q1, dst_u + stride, 0, 0); + __lsx_vstelm_d(q2, dst_u + stride2, 0, 0); + + __lsx_vstelm_d(p2, dst_v - stride3, 0, 1); + __lsx_vstelm_d(p1, dst_v - stride2, 0, 1); + __lsx_vstelm_d(p0, dst_v - stride , 0, 1); + __lsx_vstelm_d(q0, dst_v, 0, 1); + + __lsx_vstelm_d(q1, dst_v + stride, 0, 1); + __lsx_vstelm_d(q2, dst_v + stride2, 0, 1); +} + +void ff_vp8_h_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + uint8_t *temp_src; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i row0, row1, row2, row3, row4, row5, row6, row7, row8; + __m128i row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + temp_src = dst - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row0, row1, row2, row3); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row4, row5, row6, row7); + + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row8, row9, row10, row11); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row12, row13, row14, row15); + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, + row11, row12, row13, row14, row15, p3, p2, p1, p0, q0, q1, q2, q3); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + tmp0 = __lsx_vilvl_b(p1, p2); + tmp1 = __lsx_vilvl_b(q0, p0); + + tmp3 = __lsx_vilvl_h(tmp1, tmp0); + tmp4 = __lsx_vilvh_h(tmp1, tmp0); + + tmp0 = __lsx_vilvh_b(p1, p2); + tmp1 = __lsx_vilvh_b(q0, p0); + + tmp6 = __lsx_vilvl_h(tmp1, tmp0); + tmp7 = __lsx_vilvh_h(tmp1, tmp0); + + tmp2 = __lsx_vilvl_b(q2, q1); + tmp5 = __lsx_vilvh_b(q2, q1); + + temp_src = dst - 3; + VP8_ST6x1_UB(tmp3, 0, tmp2, 0, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 1, tmp2, 1, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 2, tmp2, 2, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp3, 3, tmp2, 3, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 0, tmp2, 4, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 1, tmp2, 5, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 2, tmp2, 6, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp4, 3, tmp2, 7, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 0, tmp5, 0, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 1, tmp5, 1, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 2, tmp5, 2, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp6, 3, tmp5, 3, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 0, tmp5, 4, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 1, tmp5, 5, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 2, tmp5, 6, temp_src, 4); + temp_src += stride; + VP8_ST6x1_UB(tmp7, 3, tmp5, 7, temp_src, 4); +} + +void ff_vp8_h_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, int b_limit_in, + int limit_in, int thresh_in) +{ + uint8_t *temp_src; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i mask, hev, flat, thresh, limit, b_limit; + __m128i row0, row1, row2, row3, row4, row5, row6, row7, row8; + __m128i row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + b_limit = __lsx_vreplgr2vr_b(b_limit_in); + limit = __lsx_vreplgr2vr_b(limit_in); + thresh = __lsx_vreplgr2vr_b(thresh_in); + + temp_src = dst_u - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row0, row1, row2, row3); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row4, row5, row6, row7); + + temp_src = dst_v - 4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row8, row9, row10, row11); + temp_src += stride4; + DUP4_ARG2(__lsx_vld, temp_src, 0, temp_src + stride, 0, temp_src + stride2, 0, + temp_src + stride3, 0, row12, row13, row14, row15); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, hev, mask, flat); + VP8_MBFILTER(p2, p1, p0, q0, q1, q2, mask, hev); + + tmp0 = __lsx_vilvl_b(p1, p2); + tmp1 = __lsx_vilvl_b(q0, p0); + + tmp3 = __lsx_vilvl_h(tmp1, tmp0); + tmp4 = __lsx_vilvh_h(tmp1, tmp0); + + tmp0 = __lsx_vilvh_b(p1, p2); + tmp1 = __lsx_vilvh_b(q0, p0); + + tmp6 = __lsx_vilvl_h(tmp1, tmp0); + tmp7 = __lsx_vilvh_h(tmp1, tmp0); + + tmp2 = __lsx_vilvl_b(q2, q1); + tmp5 = __lsx_vilvh_b(q2, q1); + + dst_u -= 3; + VP8_ST6x1_UB(tmp3, 0, tmp2, 0, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 1, tmp2, 1, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 2, tmp2, 2, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp3, 3, tmp2, 3, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 0, tmp2, 4, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 1, tmp2, 5, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 2, tmp2, 6, dst_u, 4); + dst_u += stride; + VP8_ST6x1_UB(tmp4, 3, tmp2, 7, dst_u, 4); + + dst_v -= 3; + VP8_ST6x1_UB(tmp6, 0, tmp5, 0, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 1, tmp5, 1, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 2, tmp5, 2, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp6, 3, tmp5, 3, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 0, tmp5, 4, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 1, tmp5, 5, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 2, tmp5, 6, dst_v, 4); + dst_v += stride; + VP8_ST6x1_UB(tmp7, 3, tmp5, 7, dst_v, 4); +} + +void ff_vp8_v_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h) +{ + __m128i mask, hev, flat; + __m128i thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + /* load vector elements */ + src -= stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, p3, p2, p1, p0); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, q0, q1, q2, q3); + thresh = __lsx_vreplgr2vr_b(h); + b_limit = __lsx_vreplgr2vr_b(e); + limit = __lsx_vreplgr2vr_b(i); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + + __lsx_vst(p1, src - stride2, 0); + __lsx_vst(p0, src - stride, 0); + __lsx_vst(q0, src, 0); + __lsx_vst(q1, src + stride, 0); +} + +void ff_vp8_h_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h) +{ + __m128i mask, hev, flat; + __m128i thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + + src -= 4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp0, tmp1, tmp2, tmp3); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp4, tmp5, tmp6, tmp7); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp8, tmp9, tmp10, tmp11); + src += stride4; + DUP4_ARG2(__lsx_vld, src, 0, src + stride, 0, src + stride2, 0, + src + stride3, 0, tmp12, tmp13, tmp14, tmp15); + src -= 3 * stride4; + + LSX_TRANSPOSE16x8_B(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, + tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(h); + b_limit = __lsx_vreplgr2vr_b(e); + limit = __lsx_vreplgr2vr_b(i); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP8_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev); + + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + + src += 2; + ST_W4(tmp2, 0, 1, 2, 3, src, stride); + ST_W4(tmp3, 0, 1, 2, 3, src, stride); + + DUP2_ARG2(__lsx_vilvh_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + + ST_W4(tmp2, 0, 1, 2, 3, src, stride); + ST_W4(tmp3, 0, 1, 2, 3, src, stride); + src -= 4 * stride4; +} diff --git a/libavcodec/loongarch/vp8_mc_lsx.c b/libavcodec/loongarch/vp8_mc_lsx.c new file mode 100644 index 0000000000..80c4f87e80 --- /dev/null +++ b/libavcodec/loongarch/vp8_mc_lsx.c @@ -0,0 +1,951 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/vp8dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp8dsp_loongarch.h" + +static const uint8_t mc_filt_mask_arr[16 * 3] = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + /* 4 width cases */ + 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 +}; + +static const int8_t subpel_filters_lsx[7][8] = { + {-6, 123, 12, -1, 0, 0, 0, 0}, + {2, -11, 108, 36, -8, 1, 0, 0}, /* New 1/4 pel 6 tap filter */ + {-9, 93, 50, -6, 0, 0, 0, 0}, + {3, -16, 77, 77, -16, 3, 0, 0}, /* New 1/2 pel 6 tap filter */ + {-6, 50, 93, -9, 0, 0, 0, 0}, + {1, -8, 36, 108, -11, 2, 0, 0}, /* New 1/4 pel 6 tap filter */ + {-1, 12, 123, -6, 0, 0, 0, 0}, +}; + +#define DPADD_SH3_SH(in0, in1, in2, coeff0, coeff1, coeff2) \ +( { \ + __m128i out0_m; \ + \ + out0_m = __lsx_vdp2_h_b(in0, coeff0); \ + out0_m = __lsx_vdp2add_h_b(out0_m, in1, coeff1); \ + out0_m = __lsx_vdp2add_h_b(out0_m, in2, coeff2); \ + \ + out0_m; \ +} ) + +#define VSHF_B3_SB(in0, in1, in2, in3, in4, in5, mask0, mask1, mask2, \ + out0, out1, out2) \ +{ \ + DUP2_ARG3(__lsx_vshuf_b, in1, in0, mask0, in3, in2, mask1, \ + out0, out1); \ + out2 = __lsx_vshuf_b(in5, in4, mask2); \ +} + +#define HORIZ_6TAP_FILT(src0, src1, mask0, mask1, mask2, \ + filt_h0, filt_h1, filt_h2) \ +( { \ + __m128i vec0_m, vec1_m, vec2_m; \ + __m128i hz_out_m; \ + \ + VSHF_B3_SB(src0, src1, src0, src1, src0, src1, mask0, mask1, mask2, \ + vec0_m, vec1_m, vec2_m); \ + hz_out_m = DPADD_SH3_SH(vec0_m, vec1_m, vec2_m, \ + filt_h0, filt_h1, filt_h2); \ + \ + hz_out_m = __lsx_vsrari_h(hz_out_m, 7); \ + hz_out_m = __lsx_vsat_h(hz_out_m, 7); \ + \ + hz_out_m; \ +} ) + +#define HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, \ + mask0, mask1, mask2, \ + filt0, filt1, filt2, \ + out0, out1, out2, out3) \ +{ \ + __m128i vec0_m, vec1_m, vec2_m, vec3_m, vec4_m, vec5_m, vec6_m, vec7_m; \ + \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, src2, \ + mask0, src3, src3, mask0, vec0_m, vec1_m, vec2_m, vec3_m); \ + DUP4_ARG2(__lsx_vdp2_h_b, vec0_m, filt0, vec1_m, filt0, vec2_m, filt0, \ + vec3_m, filt0, out0, out1, out2, out3); \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, src2, \ + mask1, src3, src3, mask1, vec0_m, vec1_m, vec2_m, vec3_m); \ + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, src2, \ + mask2, src3, src3, mask2, vec4_m, vec5_m, vec6_m, vec7_m); \ + DUP4_ARG3(__lsx_vdp2add_h_b, out0, vec0_m, filt1, out1, vec1_m, filt1, \ + out2, vec2_m, filt1, out3, vec3_m, filt1, out0, out1, out2, out3); \ + DUP4_ARG3(__lsx_vdp2add_h_b, out0, vec4_m, filt2, out1, vec5_m, filt2, \ + out2, vec6_m, filt2, out3, vec7_m, filt2, out0, out1, out2, out3); \ +} + +#define FILT_4TAP_DPADD_S_H(vec0, vec1, filt0, filt1) \ +( { \ + __m128i tmp0; \ + \ + tmp0 = __lsx_vdp2_h_b(vec0, filt0); \ + tmp0 = __lsx_vdp2add_h_b(tmp0, vec1, filt1); \ + \ + tmp0; \ +} ) + +#define HORIZ_4TAP_FILT(src0, src1, mask0, mask1, filt_h0, filt_h1) \ +( { \ + __m128i vec0_m, vec1_m; \ + __m128i hz_out_m; \ + DUP2_ARG3(__lsx_vshuf_b, src1, src0, mask0, src1, src0, mask1, \ + vec0_m, vec1_m); \ + hz_out_m = FILT_4TAP_DPADD_S_H(vec0_m, vec1_m, filt_h0, filt_h1); \ + \ + hz_out_m = __lsx_vsrari_h(hz_out_m, 7); \ + hz_out_m = __lsx_vsat_h(hz_out_m, 7); \ + \ + hz_out_m; \ +} ) + +void ff_put_vp8_epel8_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[mx - 1]; + __m128i src0, src1, src2, src3, filt0, filt1, filt2; + __m128i mask0, mask1, mask2; + __m128i out0, out1, out2, out3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 2; + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src += src_stride4; + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + for (loop_cnt = (height >> 2) - 1; loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src += src_stride4; + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + } +} + +void ff_put_vp8_epel16_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[mx - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, filt0, filt1; + __m128i filt2, mask0, mask1, mask2; + __m128i out0, out1, out2, out3, out4, out5, out6, out7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 2; + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src0 ,src2, src4, src6); + DUP4_ARG2(__lsx_vld, src, 8, src + src_stride, 8, src + src_stride2, + 8, src + src_stride3, 8, src1, src3, src5, src7); + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src6, 128, src7, 128, + src4, src5, src6, src7); + src += src_stride4; + + HORIZ_6TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + filt0, filt1, filt2, out0, out1, out2, out3); + HORIZ_6TAP_8WID_4VECS_FILT(src4, src5, src6, src7, mask0, mask1, mask2, + filt0, filt1, filt2, out4, out5, out6, out7); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + dst += dst_stride; + __lsx_vst(out1, dst, 0); + dst += dst_stride; + + DUP2_ARG3(__lsx_vssrarni_b_h, out5, out4, 7, out7, out6, 7, out4, out5); + DUP2_ARG2(__lsx_vxori_b, out4, 128, out5, 128, out4, out5); + __lsx_vst(out4, dst, 0); + dst += dst_stride; + __lsx_vst(out5, dst, 0); + dst += dst_stride; + } +} + +void ff_put_vp8_epel8_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src7, src8, src9, src10; + __m128i src10_l, src32_l, src76_l, src98_l, src21_l, src43_l, src87_l; + __m128i src109_l, filt0, filt1, filt2; + __m128i out0_l, out1_l, out2_l, out3_l; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride2; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src2, src1, src4, + src3, src10_l, src32_l, src21_l, src43_l); + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + src += src_stride4; + + DUP4_ARG2(__lsx_vilvl_b, src7, src4, src8, src7, src9, src8, src10, + src9, src76_l, src87_l, src98_l, src109_l); + + out0_l = DPADD_SH3_SH(src10_l, src32_l, src76_l, filt0, filt1, filt2); + out1_l = DPADD_SH3_SH(src21_l, src43_l, src87_l, filt0, filt1, filt2); + out2_l = DPADD_SH3_SH(src32_l, src76_l, src98_l, filt0, filt1, filt2); + out3_l = DPADD_SH3_SH(src43_l, src87_l, src109_l, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, out1_l, out0_l, 7, out3_l, out2_l, 7, + out0_l, out1_l); + DUP2_ARG2(__lsx_vxori_b, out0_l, 128, out1_l, 128, out0_l, out1_l); + + __lsx_vstelm_d(out0_l, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0_l, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1_l, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1_l, dst, 0, 1); + dst += dst_stride; + + src10_l = src76_l; + src32_l = src98_l; + src21_l = src87_l; + src43_l = src109_l; + src4 = src10; + } +} + +void ff_put_vp8_epel16_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i src10_l, src32_l, src54_l, src76_l, src21_l, src43_l, src65_l, src87_l; + __m128i src10_h, src32_h, src54_h, src76_h, src21_h, src43_h, src65_h, src87_h; + __m128i filt0, filt1, filt2; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + filt2 = __lsx_vldrepl_h(filter, 4); + + DUP4_ARG2(__lsx_vld, src - src_stride2, 0, src - src_stride, 0, src, 0, + src + src_stride, 0, src0, src1, src2, src3); + src4 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, src0, + src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src4, src3, src2, src1, + src10_l, src32_l, src43_l, src21_l); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src4, src3, src2, src1, + src10_h, src32_h, src43_h, src21_h); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + DUP4_ARG2(__lsx_vilvl_b, src5, src4, src6, src5, src7, src6, src8, src7, + src54_l, src65_l, src76_l, src87_l); + DUP4_ARG2(__lsx_vilvh_b, src5, src4, src6, src5, src7, src6, src8, src7, + src54_h, src65_h, src76_h, src87_h); + + tmp0 = DPADD_SH3_SH(src10_l, src32_l, src54_l, filt0, filt1, filt2); + tmp1 = DPADD_SH3_SH(src21_l, src43_l, src65_l, filt0, filt1, filt2); + tmp2 = DPADD_SH3_SH(src10_h, src32_h, src54_h, filt0, filt1, filt2); + tmp3 = DPADD_SH3_SH(src21_h, src43_h, src65_h, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + tmp0 = DPADD_SH3_SH(src32_l, src54_l, src76_l, filt0, filt1, filt2); + tmp1 = DPADD_SH3_SH(src43_l, src65_l, src87_l, filt0, filt1, filt2); + tmp2 = DPADD_SH3_SH(src32_h, src54_h, src76_h, filt0, filt1, filt2); + tmp3 = DPADD_SH3_SH(src43_h, src65_h, src87_h, filt0, filt1, filt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + src10_l = src54_l; + src32_l = src76_l; + src21_l = src65_l; + src43_l = src87_l; + src10_h = src54_h; + src32_h = src76_h; + src21_h = src65_h; + src43_h = src87_h; + src4 = src8; + } +} + +void ff_put_vp8_epel8_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt_hz0, filt_hz1, filt_hz2; + __m128i mask0, mask1, mask2, filt_vt0, filt_vt1, filt_vt2; + __m128i hz_out0, hz_out1, hz_out2, hz_out3, hz_out4, hz_out5, hz_out6; + __m128i hz_out7, hz_out8, out0, out1, out2, out3, out4, out5, out6, out7; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (2 + src_stride2); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + filt_hz2 = __lsx_vldrepl_h(filter_horiz, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0 ,src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + hz_out0 = HORIZ_6TAP_FILT(src0, src0, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out1 = HORIZ_6TAP_FILT(src1, src1, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out2 = HORIZ_6TAP_FILT(src2, src2, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out3 = HORIZ_6TAP_FILT(src3, src3, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out4 = HORIZ_6TAP_FILT(src4, src4, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + filt_vt2 = __lsx_vldrepl_h(filter_vert, 4); + + DUP2_ARG2(__lsx_vpackev_b, hz_out1, hz_out0, hz_out3, hz_out2, out0, out1); + DUP2_ARG2(__lsx_vpackev_b, hz_out2, hz_out1, hz_out4, hz_out3, out3, out4); + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + hz_out5 = HORIZ_6TAP_FILT(src5, src5, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out2 = __lsx_vpackev_b(hz_out5, hz_out4); + tmp0 = DPADD_SH3_SH(out0, out1, out2,filt_vt0, filt_vt1, filt_vt2); + + hz_out6 = HORIZ_6TAP_FILT(src6, src6, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out5 = __lsx_vpackev_b(hz_out6, hz_out5); + tmp1 = DPADD_SH3_SH(out3, out4, out5, filt_vt0, filt_vt1, filt_vt2); + + hz_out7 = HORIZ_6TAP_FILT(src7, src7, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + + out7 = __lsx_vpackev_b(hz_out7, hz_out6); + tmp2 = DPADD_SH3_SH(out1, out2, out7, filt_vt0, filt_vt1, filt_vt2); + + hz_out8 = HORIZ_6TAP_FILT(src8, src8, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + out6 = __lsx_vpackev_b(hz_out8, hz_out7); + tmp3 = DPADD_SH3_SH(out4, out5, out6, filt_vt0, filt_vt1, filt_vt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __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; + + hz_out4 = hz_out8; + out0 = out2; + out1 = out7; + out3 = out5; + out4 = out6; + } +} + +void ff_put_vp8_epel16_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h6v6_lsx(dst, dst_stride, src, src_stride, height, mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_epel8_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src7, src8, src9, src10; + __m128i src10_l, src72_l, src98_l, src21_l, src87_l, src109_l, filt0, filt1; + __m128i out0, out1, out2, out3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride; + + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_l, src21_l); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src7, src8, src9, src10); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src2, src8, src7, src9, src8, src10, src9, + src72_l, src87_l, src98_l, src109_l); + + out0 = FILT_4TAP_DPADD_S_H(src10_l, src72_l, filt0, filt1); + out1 = FILT_4TAP_DPADD_S_H(src21_l, src87_l, filt0, filt1); + out2 = FILT_4TAP_DPADD_S_H(src72_l, src98_l, filt0, filt1); + out3 = FILT_4TAP_DPADD_S_H(src87_l, src109_l, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src10_l = src98_l; + src21_l = src109_l; + src2 = src10; + } +} + +void ff_put_vp8_epel16_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i src10_l, src32_l, src54_l, src21_l, src43_l, src65_l, src10_h; + __m128i src32_h, src54_h, src21_h, src43_h, src65_h, filt0, filt1; + __m128i tmp0, tmp1, tmp2, tmp3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + src -= src_stride; + DUP2_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filt0, filt1); + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + DUP2_ARG2(__lsx_vilvl_b, src1, src0, src2, src1, src10_l, src21_l); + DUP2_ARG2(__lsx_vilvh_b, src1, src0, src2, src1, src10_h, src21_h); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, + 0, src + src_stride3, 0, src3, src4, src5, src6); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src3, 128, src4, 128, src5, 128, src6, 128, + src3, src4, src5, src6); + DUP4_ARG2(__lsx_vilvl_b, src3, src2, src4, src3, src5, src4, src6, + src5, src32_l, src43_l, src54_l, src65_l); + DUP4_ARG2(__lsx_vilvh_b, src3, src2, src4, src3, src5, src4, src6, + src5, src32_h, src43_h, src54_h, src65_h); + + tmp0 = FILT_4TAP_DPADD_S_H(src10_l, src32_l, filt0, filt1); + tmp1 = FILT_4TAP_DPADD_S_H(src21_l, src43_l, filt0, filt1); + tmp2 = FILT_4TAP_DPADD_S_H(src10_h, src32_h, filt0, filt1); + tmp3 = FILT_4TAP_DPADD_S_H(src21_h, src43_h, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + tmp0 = FILT_4TAP_DPADD_S_H(src32_l, src54_l, filt0, filt1); + tmp1 = FILT_4TAP_DPADD_S_H(src43_l, src65_l, filt0, filt1); + tmp2 = FILT_4TAP_DPADD_S_H(src32_h, src54_h, filt0, filt1); + tmp3 = FILT_4TAP_DPADD_S_H(src43_h, src65_h, filt0, filt1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + src10_l = src54_l; + src21_l = src65_l; + src10_h = src54_h; + src21_h = src65_h; + src2 = src6; + } +} + +void ff_put_vp8_epel8_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6; + __m128i filt_hz0, filt_hz1, filt_hz2, mask0, mask1, mask2; + __m128i filt_vt0, filt_vt1, hz_out0, hz_out1, hz_out2, hz_out3; + __m128i tmp0, tmp1, tmp2, tmp3, vec0, vec1, vec2, vec3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (2 + src_stride); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + filt_hz2 = __lsx_vldrepl_h(filter_horiz, 4); + + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + + DUP2_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src0, src1); + src2 = __lsx_vld(src + src_stride2, 0); + src += src_stride3; + + DUP2_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src0, src1); + src2 = __lsx_vxori_b(src2, 128); + hz_out0 = HORIZ_6TAP_FILT(src0, src0, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out1 = HORIZ_6TAP_FILT(src1, src1, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + hz_out2 = HORIZ_6TAP_FILT(src2, src2, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + DUP2_ARG2(__lsx_vpackev_b, hz_out1, hz_out0, hz_out2, hz_out1, vec0, vec2); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src3, src4, src5, src6); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src3, 128, src4, 128, src5, 128, src6, 128, + src3, src4, src5, src6); + + hz_out3 = HORIZ_6TAP_FILT(src3, src3, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec1 = __lsx_vpackev_b(hz_out3, hz_out2); + tmp0 = FILT_4TAP_DPADD_S_H(vec0, vec1, filt_vt0, filt_vt1); + + hz_out0 = HORIZ_6TAP_FILT(src4, src4, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec3 = __lsx_vpackev_b(hz_out0, hz_out3); + tmp1 = FILT_4TAP_DPADD_S_H(vec2, vec3, filt_vt0, filt_vt1); + + hz_out1 = HORIZ_6TAP_FILT(src5, src5, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + vec0 = __lsx_vpackev_b(hz_out1, hz_out0); + tmp2 = FILT_4TAP_DPADD_S_H(vec1, vec0, filt_vt0, filt_vt1); + + hz_out2 = HORIZ_6TAP_FILT(src6, src6, mask0, mask1, mask2, filt_hz0, + filt_hz1, filt_hz2); + DUP2_ARG2(__lsx_vpackev_b, hz_out0, hz_out3, hz_out2, hz_out1, vec1, vec2); + tmp3 = FILT_4TAP_DPADD_S_H(vec1, vec2, filt_vt0, filt_vt1); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __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; + } +} + +void ff_put_vp8_epel16_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h6v4_lsx(dst, dst_stride, src, src_stride, height, + mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_epel8_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + uint32_t loop_cnt; + const int8_t *filter_horiz = subpel_filters_lsx[mx - 1]; + const int8_t *filter_vert = subpel_filters_lsx[my - 1]; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8; + __m128i filt_hz0, filt_hz1, mask0, mask1; + __m128i filt_vt0, filt_vt1, filt_vt2; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + __m128i out0, out1, out2, out3, out4, out5, out6, out7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= (1 + src_stride2); + + /* rearranging filter */ + DUP2_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filt_hz0, filt_hz1); + mask1 = __lsx_vaddi_bu(mask0, 2); + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + src4 = __lsx_vld(src, 0); + src += src_stride; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + src4 = __lsx_vxori_b(src4, 128); + + tmp0 = HORIZ_4TAP_FILT(src0, src0, mask0, mask1, filt_hz0, filt_hz1); + tmp1 = HORIZ_4TAP_FILT(src1, src1, mask0, mask1, filt_hz0, filt_hz1); + tmp2 = HORIZ_4TAP_FILT(src2, src2, mask0, mask1, filt_hz0, filt_hz1); + tmp3 = HORIZ_4TAP_FILT(src3, src3, mask0, mask1, filt_hz0, filt_hz1); + tmp4 = HORIZ_4TAP_FILT(src4, src4, mask0, mask1, filt_hz0, filt_hz1); + + DUP4_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp2, tmp1, + tmp4, tmp3, out0, out1, out3, out4); + + DUP2_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filt_vt0, filt_vt1); + filt_vt2 = __lsx_vldrepl_h(filter_vert, 4); + + for (loop_cnt = (height >> 2); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src5, src6, src7, src8); + src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src5, 128, src6, 128, src7, 128, src8, 128, + src5, src6, src7, src8); + + tmp5 = HORIZ_4TAP_FILT(src5, src5, mask0, mask1, filt_hz0, filt_hz1); + out2 = __lsx_vpackev_b(tmp5, tmp4); + tmp0 = DPADD_SH3_SH(out0, out1, out2, filt_vt0, filt_vt1, filt_vt2); + + tmp6 = HORIZ_4TAP_FILT(src6, src6, mask0, mask1, filt_hz0, filt_hz1); + out5 = __lsx_vpackev_b(tmp6, tmp5); + tmp1 = DPADD_SH3_SH(out3, out4, out5, filt_vt0, filt_vt1, filt_vt2); + + tmp7 = HORIZ_4TAP_FILT(src7, src7, mask0, mask1, filt_hz0, filt_hz1); + out6 = __lsx_vpackev_b(tmp7, tmp6); + tmp2 = DPADD_SH3_SH(out1, out2, out6, filt_vt0, filt_vt1, filt_vt2); + + tmp8 = HORIZ_4TAP_FILT(src8, src8, mask0, mask1, filt_hz0, filt_hz1); + out7 = __lsx_vpackev_b(tmp8, tmp7); + tmp3 = DPADD_SH3_SH(out4, out5, out7, filt_vt0, filt_vt1, filt_vt2); + + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + + __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; + + tmp4 = tmp8; + out0 = out2; + out1 = out6; + out3 = out5; + out4 = out7; + } +} + +void ff_put_vp8_epel16_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + ff_put_vp8_epel8_h4v6_lsx(dst, dst_stride, src, src_stride, height, + mx, my); + src += 8; + dst += 8; + } +} + +void ff_put_vp8_pixels8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t cnt; + __m128i src0, src1, src2, src3; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + if (0 == height % 8) { + for (cnt = height >> 3; cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } + } else if( 0 == height % 4) { + for (cnt = (height >> 2); cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += src_stride4; + + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } + } +} + +void ff_put_vp8_pixels16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int height, int mx, int my) +{ + int32_t width = 16; + int32_t cnt, loop_cnt; + uint8_t *src_tmp, *dst_tmp; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + + ptrdiff_t src_stride2 = src_stride << 1; + ptrdiff_t src_stride3 = src_stride2 + src_stride; + ptrdiff_t src_stride4 = src_stride2 << 1; + + ptrdiff_t dst_stride2 = dst_stride << 1; + ptrdiff_t dst_stride3 = dst_stride2 + dst_stride; + ptrdiff_t dst_stride4 = dst_stride2 << 1; + + if (0 == height % 8) { + for (cnt = (width >> 4); cnt--;) { + src_tmp = src; + dst_tmp = dst; + for (loop_cnt = (height >> 3); loop_cnt--;) { + DUP4_ARG2(__lsx_vld, src_tmp, 0, src_tmp + src_stride, 0, + src_tmp + src_stride2, 0, src_tmp + src_stride3, 0, + src4, src5, src6, src7); + src_tmp += src_stride4; + + __lsx_vst(src4, dst_tmp, 0); + __lsx_vst(src5, dst_tmp + dst_stride, 0); + __lsx_vst(src6, dst_tmp + dst_stride2, 0); + __lsx_vst(src7, dst_tmp + dst_stride3, 0); + dst_tmp += dst_stride4; + + DUP4_ARG2(__lsx_vld, src_tmp, 0, src_tmp + src_stride, 0, + src_tmp + src_stride2, 0, src_tmp + src_stride3, 0, + src4, src5, src6, src7); + src_tmp += src_stride4; + + __lsx_vst(src4, dst_tmp, 0); + __lsx_vst(src5, dst_tmp + dst_stride, 0); + __lsx_vst(src6, dst_tmp + dst_stride2, 0); + __lsx_vst(src7, dst_tmp + dst_stride3, 0); + dst_tmp += dst_stride4; + } + src += 16; + dst += 16; + } + } else if (0 == height % 4) { + for (cnt = (height >> 2); cnt--;) { + DUP4_ARG2(__lsx_vld, src, 0, src + src_stride, 0, src + src_stride2, 0, + src + src_stride3, 0, src0, src1, src2, src3); + src += 4 * src_stride4; + + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst + dst_stride, 0); + __lsx_vst(src2, dst + dst_stride2, 0); + __lsx_vst(src3, dst + dst_stride3, 0); + dst += dst_stride4; + } + } +} diff --git a/libavcodec/loongarch/vp8dsp_init_loongarch.c b/libavcodec/loongarch/vp8dsp_init_loongarch.c new file mode 100644 index 0000000000..63da15b198 --- /dev/null +++ b/libavcodec/loongarch/vp8dsp_init_loongarch.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + * VP8 compatible video decoder + */ + +#include "libavutil/loongarch/cpu.h" +#include "libavcodec/vp8dsp.h" +#include "libavutil/attributes.h" +#include "vp8dsp_loongarch.h" + +#define VP8_MC_LOONGARCH_FUNC(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][2] = ff_put_vp8_epel##SIZE##_h6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][0] = ff_put_vp8_epel##SIZE##_v4_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][1][2] = ff_put_vp8_epel##SIZE##_h6v4_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][0] = ff_put_vp8_epel##SIZE##_v6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][1] = ff_put_vp8_epel##SIZE##_h4v6_lsx; \ + dsp->put_vp8_epel_pixels_tab[IDX][2][2] = ff_put_vp8_epel##SIZE##_h6v6_lsx; + +#define VP8_MC_LOONGARCH_COPY(IDX, SIZE) \ + dsp->put_vp8_epel_pixels_tab[IDX][0][0] = ff_put_vp8_pixels##SIZE##_lsx; \ + dsp->put_vp8_bilinear_pixels_tab[IDX][0][0] = ff_put_vp8_pixels##SIZE##_lsx; + +av_cold void ff_vp8dsp_init_loongarch(VP8DSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (have_lsx(cpu_flags)) { + VP8_MC_LOONGARCH_FUNC(0, 16); + VP8_MC_LOONGARCH_FUNC(1, 8); + + VP8_MC_LOONGARCH_COPY(0, 16); + VP8_MC_LOONGARCH_COPY(1, 8); + + dsp->vp8_v_loop_filter16y = ff_vp8_v_loop_filter16_lsx; + dsp->vp8_h_loop_filter16y = ff_vp8_h_loop_filter16_lsx; + dsp->vp8_v_loop_filter8uv = ff_vp8_v_loop_filter8uv_lsx; + dsp->vp8_h_loop_filter8uv = ff_vp8_h_loop_filter8uv_lsx; + + dsp->vp8_v_loop_filter16y_inner = ff_vp8_v_loop_filter16_inner_lsx; + dsp->vp8_h_loop_filter16y_inner = ff_vp8_h_loop_filter16_inner_lsx; + } +} diff --git a/libavcodec/loongarch/vp8dsp_loongarch.h b/libavcodec/loongarch/vp8dsp_loongarch.h new file mode 100644 index 0000000000..87e9509db9 --- /dev/null +++ b/libavcodec/loongarch/vp8dsp_loongarch.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Hecai Yuan + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VP8DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VP8DSP_LOONGARCH_H + +#include "libavcodec/vp8dsp.h" + +void ff_put_vp8_pixels8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int x, int y); +void ff_put_vp8_pixels16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int x, int y); + +void ff_put_vp8_epel16_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel16_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +void ff_put_vp8_epel8_v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h6v4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h4v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); +void ff_put_vp8_epel8_h6v6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +void ff_put_vp8_epel8_h6_lsx(uint8_t *dst, ptrdiff_t dst_stride, + uint8_t *src, ptrdiff_t src_stride, + int h, int mx, int my); + +/* loop filter */ +void ff_vp8_v_loop_filter16_inner_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h); +void ff_vp8_h_loop_filter16_inner_lsx(uint8_t *src, ptrdiff_t stride, + int32_t e, int32_t i, int32_t h); + +void ff_vp8_v_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_h_loop_filter16_lsx(uint8_t *dst, ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_h_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); +void ff_vp8_v_loop_filter8uv_lsx(uint8_t *dst_u, uint8_t *dst_v, + ptrdiff_t stride, + int flim_e, int flim_i, int hev_thresh); + +#endif // #ifndef AVCODEC_LOONGARCH_VP8DSP_LOONGARCH_H diff --git a/libavcodec/loongarch/vp9_idct_lsx.c b/libavcodec/loongarch/vp9_idct_lsx.c new file mode 100644 index 0000000000..88805814c6 --- /dev/null +++ b/libavcodec/loongarch/vp9_idct_lsx.c @@ -0,0 +1,1411 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Jin Bo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" +#include "libavutil/attributes.h" + +#define VP9_DCT_CONST_BITS 14 +#define ALLOC_ALIGNED(align) __attribute__ ((aligned(align))) +#define ROUND_POWER_OF_TWO(value, n) (((value) + (1 << ((n) - 1))) >> (n)) + +const int32_t cospi_1_64 = 16364; +const int32_t cospi_2_64 = 16305; +const int32_t cospi_3_64 = 16207; +const int32_t cospi_4_64 = 16069; +const int32_t cospi_5_64 = 15893; +const int32_t cospi_6_64 = 15679; +const int32_t cospi_7_64 = 15426; +const int32_t cospi_8_64 = 15137; +const int32_t cospi_9_64 = 14811; +const int32_t cospi_10_64 = 14449; +const int32_t cospi_11_64 = 14053; +const int32_t cospi_12_64 = 13623; +const int32_t cospi_13_64 = 13160; +const int32_t cospi_14_64 = 12665; +const int32_t cospi_15_64 = 12140; +const int32_t cospi_16_64 = 11585; +const int32_t cospi_17_64 = 11003; +const int32_t cospi_18_64 = 10394; +const int32_t cospi_19_64 = 9760; +const int32_t cospi_20_64 = 9102; +const int32_t cospi_21_64 = 8423; +const int32_t cospi_22_64 = 7723; +const int32_t cospi_23_64 = 7005; +const int32_t cospi_24_64 = 6270; +const int32_t cospi_25_64 = 5520; +const int32_t cospi_26_64 = 4756; +const int32_t cospi_27_64 = 3981; +const int32_t cospi_28_64 = 3196; +const int32_t cospi_29_64 = 2404; +const int32_t cospi_30_64 = 1606; +const int32_t cospi_31_64 = 804; + +const int32_t sinpi_1_9 = 5283; +const int32_t sinpi_2_9 = 9929; +const int32_t sinpi_3_9 = 13377; +const int32_t sinpi_4_9 = 15212; + +#define VP9_DOTP_CONST_PAIR(reg0, reg1, cnst0, cnst1, out0, out1) \ +{ \ + __m128i k0_m = __lsx_vreplgr2vr_h(cnst0); \ + __m128i s0_m, s1_m, s2_m, s3_m; \ + \ + s0_m = __lsx_vreplgr2vr_h(cnst1); \ + k0_m = __lsx_vpackev_h(s0_m, k0_m); \ + \ + s1_m = __lsx_vilvl_h(__lsx_vneg_h(reg1), reg0); \ + s0_m = __lsx_vilvh_h(__lsx_vneg_h(reg1), reg0); \ + s3_m = __lsx_vilvl_h(reg0, reg1); \ + s2_m = __lsx_vilvh_h(reg0, reg1); \ + DUP2_ARG2(__lsx_vdp2_w_h, s1_m, k0_m, s0_m, k0_m, s1_m, s0_m); \ + DUP2_ARG2(__lsx_vsrari_w, s1_m, VP9_DCT_CONST_BITS, \ + s0_m, VP9_DCT_CONST_BITS, s1_m, s0_m); \ + out0 = __lsx_vpickev_h(s0_m, s1_m); \ + DUP2_ARG2(__lsx_vdp2_w_h, s3_m, k0_m, s2_m, k0_m, s1_m, s0_m); \ + DUP2_ARG2(__lsx_vsrari_w, s1_m, VP9_DCT_CONST_BITS, \ + s0_m, VP9_DCT_CONST_BITS, s1_m, s0_m); \ + out1 = __lsx_vpickev_h(s0_m, s1_m); \ +} + +#define VP9_SET_COSPI_PAIR(c0_h, c1_h) \ +( { \ + __m128i out0_m, r0_m, r1_m; \ + \ + r0_m = __lsx_vreplgr2vr_h(c0_h); \ + r1_m = __lsx_vreplgr2vr_h(c1_h); \ + out0_m = __lsx_vpackev_h(r1_m, r0_m); \ + \ + out0_m; \ +} ) + +#define VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3) \ +{ \ + uint8_t *dst_m = (uint8_t *) (dst); \ + __m128i dst0_m, dst1_m, dst2_m, dst3_m; \ + __m128i tmp0_m, tmp1_m; \ + __m128i res0_m, res1_m, res2_m, res3_m; \ + __m128i zero_m = __lsx_vldi(0); \ + DUP4_ARG2(__lsx_vld, dst_m, 0, dst_m + dst_stride, 0, \ + dst_m + 2 * dst_stride, 0, dst_m + 3 * dst_stride, 0, \ + dst0_m, dst1_m, dst2_m, dst3_m); \ + DUP4_ARG2(__lsx_vilvl_b, zero_m, dst0_m, zero_m, dst1_m, zero_m, \ + dst2_m, zero_m, dst3_m, res0_m, res1_m, res2_m, res3_m);\ + DUP4_ARG2(__lsx_vadd_h, res0_m, in0, res1_m, in1, res2_m, in2, \ + res3_m, in3, res0_m, res1_m, res2_m, res3_m); \ + DUP4_ARG1(__lsx_vclip255_h, res0_m, res1_m, res2_m, res3_m, \ + res0_m, res1_m, res2_m, res3_m); \ + DUP2_ARG2(__lsx_vpickev_b, res1_m, res0_m, res3_m, res2_m, \ + tmp0_m, tmp1_m); \ + __lsx_vstelm_d(tmp0_m, dst_m, 0, 0); \ + __lsx_vstelm_d(tmp0_m, dst_m + dst_stride, 0, 1); \ + __lsx_vstelm_d(tmp1_m, dst_m + 2 * dst_stride, 0, 0); \ + __lsx_vstelm_d(tmp1_m, dst_m + 3 * dst_stride, 0, 1); \ +} + +#define VP9_UNPCK_UB_SH(in, out_h, out_l) \ +{ \ + __m128i zero = __lsx_vldi(0); \ + out_l = __lsx_vilvl_b(zero, in); \ + out_h = __lsx_vilvh_b(zero, in); \ +} + +#define VP9_ILVLTRANS4x8_H(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3, out4, out5, out6, out7) \ +{ \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + __m128i tmp0_n, tmp1_n, tmp2_n, tmp3_n; \ + __m128i zero_m = __lsx_vldi(0); \ + \ + DUP4_ARG2(__lsx_vilvl_h, in1, in0, in3, in2, in5, in4, in7, in6, \ + tmp0_n, tmp1_n, tmp2_n, tmp3_n); \ + tmp0_m = __lsx_vilvl_w(tmp1_n, tmp0_n); \ + tmp2_m = __lsx_vilvh_w(tmp1_n, tmp0_n); \ + tmp1_m = __lsx_vilvl_w(tmp3_n, tmp2_n); \ + tmp3_m = __lsx_vilvh_w(tmp3_n, tmp2_n); \ + \ + out0 = __lsx_vilvl_d(tmp1_m, tmp0_m); \ + out1 = __lsx_vilvh_d(tmp1_m, tmp0_m); \ + out2 = __lsx_vilvl_d(tmp3_m, tmp2_m); \ + out3 = __lsx_vilvh_d(tmp3_m, tmp2_m); \ + \ + out4 = zero_m; \ + out5 = zero_m; \ + out6 = zero_m; \ + out7 = zero_m; \ +} + +/* multiply and add macro */ +#define VP9_MADD(inp0, inp1, inp2, inp3, cst0, cst1, cst2, cst3, \ + out0, out1, out2, out3) \ +{ \ + __m128i madd_s0_m, madd_s1_m, madd_s2_m, madd_s3_m; \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + \ + madd_s1_m = __lsx_vilvl_h(inp1, inp0); \ + madd_s0_m = __lsx_vilvh_h(inp1, inp0); \ + madd_s3_m = __lsx_vilvl_h(inp3, inp2); \ + madd_s2_m = __lsx_vilvh_h(inp3, inp2); \ + DUP4_ARG2(__lsx_vdp2_w_h, madd_s1_m, cst0, madd_s0_m, cst0, \ + madd_s1_m, cst1, madd_s0_m, cst1, tmp0_m, tmp1_m, \ + tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, tmp1_m, \ + VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, tmp3_m, \ + VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, out0, out1); \ + DUP4_ARG2(__lsx_vdp2_w_h, madd_s3_m, cst2, madd_s2_m, cst2, madd_s3_m, \ + cst3, madd_s2_m, cst3, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, \ + tmp1_m, VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, \ + tmp3_m, VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, out2, out3); \ +} + +#define VP9_SET_CONST_PAIR(mask_h, idx1_h, idx2_h) \ +( { \ + __m128i c0_m, c1_m; \ + \ + DUP2_ARG2(__lsx_vreplvei_h, mask_h, idx1_h, mask_h, idx2_h, c0_m, c1_m); \ + c0_m = __lsx_vpackev_h(c1_m, c0_m); \ + \ + c0_m; \ +} ) + +/* idct 8x8 macro */ +#define VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3, out4, out5, out6, out7) \ +{ \ + __m128i tp0_m, tp1_m, tp2_m, tp3_m, tp4_m, tp5_m, tp6_m, tp7_m; \ + __m128i k0_m, k1_m, k2_m, k3_m, res0_m, res1_m, res2_m, res3_m; \ + __m128i tmp0_m, tmp1_m, tmp2_m, tmp3_m; \ + v8i16 mask_m = { cospi_28_64, cospi_4_64, cospi_20_64, cospi_12_64, \ + cospi_16_64, -cospi_4_64, -cospi_20_64, -cospi_16_64 }; \ + \ + k0_m = VP9_SET_CONST_PAIR(mask_m, 0, 5); \ + k1_m = VP9_SET_CONST_PAIR(mask_m, 1, 0); \ + k2_m = VP9_SET_CONST_PAIR(mask_m, 6, 3); \ + k3_m = VP9_SET_CONST_PAIR(mask_m, 3, 2); \ + VP9_MADD(in1, in7, in3, in5, k0_m, k1_m, k2_m, k3_m, in1, in7, in3, in5); \ + DUP2_ARG2(__lsx_vsub_h, in1, in3, in7, in5, res0_m, res1_m); \ + k0_m = VP9_SET_CONST_PAIR(mask_m, 4, 7); \ + k1_m = __lsx_vreplvei_h(mask_m, 4); \ + \ + res2_m = __lsx_vilvl_h(res0_m, res1_m); \ + res3_m = __lsx_vilvh_h(res0_m, res1_m); \ + DUP4_ARG2(__lsx_vdp2_w_h, res2_m, k0_m, res3_m, k0_m, res2_m, k1_m, \ + res3_m, k1_m, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + DUP4_ARG2(__lsx_vsrari_w, tmp0_m, VP9_DCT_CONST_BITS, \ + tmp1_m, VP9_DCT_CONST_BITS, tmp2_m, VP9_DCT_CONST_BITS, \ + tmp3_m, VP9_DCT_CONST_BITS, tmp0_m, tmp1_m, tmp2_m, tmp3_m); \ + tp4_m = __lsx_vadd_h(in1, in3); \ + DUP2_ARG2(__lsx_vpickev_h, tmp1_m, tmp0_m, tmp3_m, tmp2_m, tp5_m, tp6_m); \ + tp7_m = __lsx_vadd_h(in7, in5); \ + k2_m = VP9_SET_COSPI_PAIR(cospi_24_64, -cospi_8_64); \ + k3_m = VP9_SET_COSPI_PAIR(cospi_8_64, cospi_24_64); \ + VP9_MADD(in0, in4, in2, in6, k1_m, k0_m, k2_m, k3_m, \ + in0, in4, in2, in6); \ + LSX_BUTTERFLY_4_H(in0, in4, in2, in6, tp0_m, tp1_m, tp2_m, tp3_m); \ + LSX_BUTTERFLY_8_H(tp0_m, tp1_m, tp2_m, tp3_m, tp4_m, tp5_m, tp6_m, tp7_m, \ + out0, out1, out2, out3, out4, out5, out6, out7); \ +} + +static av_always_inline +void vp9_idct8x8_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int16_t out; + int32_t val; + __m128i vec; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + val = ROUND_POWER_OF_TWO(out, 5); + vec = __lsx_vreplgr2vr_h(val); + input[0] = 0; + + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, vec, vec, vec, vec); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, vec, vec, vec, vec); +} + +static void vp9_idct8x8_12_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i s0, s1, s2, s3, s4, s5, s6, s7, k0, k1, k2, k3, m0, m1, m2, m3; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i zero = __lsx_vldi(0); + + /* load vector elements of 8x8 block */ + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + in4, in5, in6, in7); + __lsx_vst(zero, input, 0); + __lsx_vst(zero, input, 16); + __lsx_vst(zero, input, 32); + __lsx_vst(zero, input, 48); + __lsx_vst(zero, input, 64); + __lsx_vst(zero, input, 80); + __lsx_vst(zero, input, 96); + __lsx_vst(zero, input, 112); + DUP4_ARG2(__lsx_vilvl_d,in1, in0, in3, in2, in5, in4, in7, + in6, in0, in1, in2, in3); + + /* stage1 */ + DUP2_ARG2(__lsx_vilvh_h, in3, in0, in2, in1, s0, s1); + k0 = VP9_SET_COSPI_PAIR(cospi_28_64, -cospi_4_64); + k1 = VP9_SET_COSPI_PAIR(cospi_4_64, cospi_28_64); + k2 = VP9_SET_COSPI_PAIR(-cospi_20_64, cospi_12_64); + k3 = VP9_SET_COSPI_PAIR(cospi_12_64, cospi_20_64); + DUP4_ARG2(__lsx_vdp2_w_h, s0, k0, s0, k1, s1, k2, s1, k3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp2, VP9_DCT_CONST_BITS, tmp3, + VP9_DCT_CONST_BITS, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, zero, tmp2, zero, tmp3, + s0, s1, s2, s3); + LSX_BUTTERFLY_4_H(s0, s1, s3, s2, s4, s7, s6, s5); + + /* stage2 */ + DUP2_ARG2(__lsx_vilvl_h, in3, in1, in2, in0, s1, s0); + k0 = VP9_SET_COSPI_PAIR(cospi_16_64, cospi_16_64); + k1 = VP9_SET_COSPI_PAIR(cospi_16_64, -cospi_16_64); + k2 = VP9_SET_COSPI_PAIR(cospi_24_64, -cospi_8_64); + k3 = VP9_SET_COSPI_PAIR(cospi_8_64, cospi_24_64); + DUP4_ARG2(__lsx_vdp2_w_h, s0, k0, s0, k1, s1, k2, s1, k3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp2, VP9_DCT_CONST_BITS, tmp3, + VP9_DCT_CONST_BITS, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, zero, tmp2, zero, tmp3, + s0, s1, s2, s3); + LSX_BUTTERFLY_4_H(s0, s1, s2, s3, m0, m1, m2, m3); + + /* stage3 */ + s0 = __lsx_vilvl_h(s6, s5); + + k1 = VP9_SET_COSPI_PAIR(-cospi_16_64, cospi_16_64); + DUP2_ARG2(__lsx_vdp2_w_h, s0, k1, s0, k0, tmp0, tmp1); + DUP2_ARG2(__lsx_vsrari_w, tmp0, VP9_DCT_CONST_BITS, tmp1, + VP9_DCT_CONST_BITS, tmp0, tmp1); + DUP2_ARG2(__lsx_vpickev_h, zero, tmp0, zero, tmp1, s2, s3); + + /* stage4 */ + LSX_BUTTERFLY_8_H(m0, m1, m2, m3, s4, s2, s3, s7, + in0, in1, in2, in3, in4, in5, in6, in7); + VP9_ILVLTRANS4x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + + /* final rounding (add 2^4, divide by 2^5) and shift */ + DUP4_ARG2(__lsx_vsrari_h, in0 , 5, in1, 5, in2, 5, in3, 5, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsrari_h, in4 , 5, in5, 5, in6, 5, in7, 5, + in4, in5, in6, in7); + + /* add block and store 8x8 */ + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in4, in5, in6, in7); +} + +static void vp9_idct8x8_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i in0, in1, in2, in3, in4, in5, in6, in7; + __m128i zero = __lsx_vldi(0); + + /* load vector elements of 8x8 block */ + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + in4, in5, in6, in7); + __lsx_vst(zero, input, 0); + __lsx_vst(zero, input, 16); + __lsx_vst(zero, input, 32); + __lsx_vst(zero, input, 48); + __lsx_vst(zero, input, 64); + __lsx_vst(zero, input, 80); + __lsx_vst(zero, input, 96); + __lsx_vst(zero, input, 112); + /* 1D idct8x8 */ + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* columns transform */ + LSX_TRANSPOSE8x8_H(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* 1D idct8x8 */ + VP9_IDCT8x8_1D(in0, in1, in2, in3, in4, in5, in6, in7, + in0, in1, in2, in3, in4, in5, in6, in7); + /* final rounding (add 2^4, divide by 2^5) and shift */ + DUP4_ARG2(__lsx_vsrari_h, in0, 5, in1, 5, in2, 5, in3, 5, + in0, in1, in2, in3); + DUP4_ARG2(__lsx_vsrari_h, in4, 5, in5, 5, in6, 5, in7, 5, + in4, in5, in6, in7); + /* add block and store 8x8 */ + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in0, in1, in2, in3); + dst += (4 * dst_stride); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, in4, in5, in6, in7); +} + +static void vp9_idct16_1d_columns_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + __m128i loc0, loc1, loc2, loc3; + __m128i reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14; + __m128i reg1, reg3, reg5, reg7, reg9, reg11, reg13, reg15; + __m128i tmp5, tmp6, tmp7; + __m128i zero = __lsx_vldi(0); + int32_t offset = dst_stride << 2; + + DUP4_ARG2(__lsx_vld, input, 32*0, input, 32*1, input, 32*2, input, 32*3, + reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, input, 32*4, input, 32*5, input, 32*6, input, 32*7, + reg4, reg5, reg6, reg7); + DUP4_ARG2(__lsx_vld, input, 32*8, input, 32*9, input, 32*10, input, 32*11, + reg8, reg9, reg10, reg11); + DUP4_ARG2(__lsx_vld, input, 32*12, input, 32*13, input, 32*14, input, + 32*15, reg12, reg13, reg14, reg15); + + __lsx_vst(zero, input, 32*0); + __lsx_vst(zero, input, 32*1); + __lsx_vst(zero, input, 32*2); + __lsx_vst(zero, input, 32*3); + __lsx_vst(zero, input, 32*4); + __lsx_vst(zero, input, 32*5); + __lsx_vst(zero, input, 32*6); + __lsx_vst(zero, input, 32*7); + __lsx_vst(zero, input, 32*8); + __lsx_vst(zero, input, 32*9); + __lsx_vst(zero, input, 32*10); + __lsx_vst(zero, input, 32*11); + __lsx_vst(zero, input, 32*12); + __lsx_vst(zero, input, 32*13); + __lsx_vst(zero, input, 32*14); + __lsx_vst(zero, input, 32*15); + + VP9_DOTP_CONST_PAIR(reg2, reg14, cospi_28_64, cospi_4_64, reg2, reg14); + VP9_DOTP_CONST_PAIR(reg10, reg6, cospi_12_64, cospi_20_64, reg10, reg6); + LSX_BUTTERFLY_4_H(reg2, reg14, reg6, reg10, loc0, loc1, reg14, reg2); + VP9_DOTP_CONST_PAIR(reg14, reg2, cospi_16_64, cospi_16_64, loc2, loc3); + VP9_DOTP_CONST_PAIR(reg0, reg8, cospi_16_64, cospi_16_64, reg0, reg8); + VP9_DOTP_CONST_PAIR(reg4, reg12, cospi_24_64, cospi_8_64, reg4, reg12); + LSX_BUTTERFLY_4_H(reg8, reg0, reg4, reg12, reg2, reg6, reg10, reg14); + + reg0 = __lsx_vsub_h(reg2, loc1); + reg2 = __lsx_vadd_h(reg2, loc1); + reg12 = __lsx_vsub_h(reg14, loc0); + reg14 = __lsx_vadd_h(reg14, loc0); + reg4 = __lsx_vsub_h(reg6, loc3); + reg6 = __lsx_vadd_h(reg6, loc3); + reg8 = __lsx_vsub_h(reg10, loc2); + reg10 = __lsx_vadd_h(reg10, loc2); + + /* stage2 */ + VP9_DOTP_CONST_PAIR(reg1, reg15, cospi_30_64, cospi_2_64, reg1, reg15); + VP9_DOTP_CONST_PAIR(reg9, reg7, cospi_14_64, cospi_18_64, loc2, loc3); + + reg9 = __lsx_vsub_h(reg1, loc2); + reg1 = __lsx_vadd_h(reg1, loc2); + reg7 = __lsx_vsub_h(reg15, loc3); + reg15 = __lsx_vadd_h(reg15, loc3); + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_22_64, cospi_10_64, reg5, reg11); + VP9_DOTP_CONST_PAIR(reg13, reg3, cospi_6_64, cospi_26_64, loc0, loc1); + LSX_BUTTERFLY_4_H(loc0, loc1, reg11, reg5, reg13, reg3, reg11, reg5); + + loc1 = __lsx_vadd_h(reg15, reg3); + reg3 = __lsx_vsub_h(reg15, reg3); + loc2 = __lsx_vadd_h(reg2, loc1); + reg15 = __lsx_vsub_h(reg2, loc1); + + loc1 = __lsx_vadd_h(reg1, reg13); + reg13 = __lsx_vsub_h(reg1, reg13); + loc0 = __lsx_vadd_h(reg0, loc1); + loc1 = __lsx_vsub_h(reg0, loc1); + tmp6 = loc0; + tmp7 = loc1; + reg0 = loc2; + + VP9_DOTP_CONST_PAIR(reg7, reg9, cospi_24_64, cospi_8_64, reg7, reg9); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg5), __lsx_vneg_h(reg11), cospi_8_64, + cospi_24_64, reg5, reg11); + + loc0 = __lsx_vadd_h(reg9, reg5); + reg5 = __lsx_vsub_h(reg9, reg5); + reg2 = __lsx_vadd_h(reg6, loc0); + reg1 = __lsx_vsub_h(reg6, loc0); + + loc0 = __lsx_vadd_h(reg7, reg11); + reg11 = __lsx_vsub_h(reg7, reg11); + loc1 = __lsx_vadd_h(reg4, loc0); + loc2 = __lsx_vsub_h(reg4, loc0); + tmp5 = loc1; + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_16_64, cospi_16_64, reg5, reg11); + LSX_BUTTERFLY_4_H(reg8, reg10, reg11, reg5, loc0, reg4, reg9, loc1); + + reg10 = loc0; + reg11 = loc1; + + VP9_DOTP_CONST_PAIR(reg3, reg13, cospi_16_64, cospi_16_64, reg3, reg13); + LSX_BUTTERFLY_4_H(reg12, reg14, reg13, reg3, reg8, reg6, reg7, reg5); + reg13 = loc2; + + /* Transpose and store the output */ + reg12 = tmp5; + reg14 = tmp6; + reg3 = tmp7; + + DUP4_ARG2(__lsx_vsrari_h, reg0, 6, reg2, 6, reg4, 6, reg6, 6, + reg0, reg2, reg4, reg6); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg0, reg2, reg4, reg6); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg8, 6, reg10, 6, reg12, 6, reg14, 6, + reg8, reg10, reg12, reg14); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg8, reg10, reg12, reg14); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg3, 6, reg5, 6, reg11, 6, reg13, 6, + reg3, reg5, reg11, reg13); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg3, reg13, reg11, reg5); + dst += offset; + DUP4_ARG2(__lsx_vsrari_h, reg1, 6, reg7, 6, reg9, 6, reg15, 6, + reg1, reg7, reg9, reg15); + VP9_ADDBLK_ST8x4_UB(dst, dst_stride, reg7, reg9, reg1, reg15); +} + +static void vp9_idct16_1d_columns_lsx(int16_t *input, int16_t *output) +{ + __m128i loc0, loc1, loc2, loc3; + __m128i reg1, reg3, reg5, reg7, reg9, reg11, reg13, reg15; + __m128i reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14; + __m128i tmp5, tmp6, tmp7; + __m128i zero = __lsx_vldi(0); + int16_t *offset; + + DUP4_ARG2(__lsx_vld, input, 32*0, input, 32*1, input, 32*2, input, 32*3, + reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, input, 32*4, input, 32*5, input, 32*6, input, 32*7, + reg4, reg5, reg6, reg7); + DUP4_ARG2(__lsx_vld, input, 32*8, input, 32*9, input, 32*10, input, 32*11, + reg8, reg9, reg10, reg11); + DUP4_ARG2(__lsx_vld, input, 32*12, input, 32*13, input, 32*14, input, + 32*15, reg12, reg13, reg14, reg15); + + __lsx_vst(zero, input, 32*0); + __lsx_vst(zero, input, 32*1); + __lsx_vst(zero, input, 32*2); + __lsx_vst(zero, input, 32*3); + __lsx_vst(zero, input, 32*4); + __lsx_vst(zero, input, 32*5); + __lsx_vst(zero, input, 32*6); + __lsx_vst(zero, input, 32*7); + __lsx_vst(zero, input, 32*8); + __lsx_vst(zero, input, 32*9); + __lsx_vst(zero, input, 32*10); + __lsx_vst(zero, input, 32*11); + __lsx_vst(zero, input, 32*12); + __lsx_vst(zero, input, 32*13); + __lsx_vst(zero, input, 32*14); + __lsx_vst(zero, input, 32*15); + + VP9_DOTP_CONST_PAIR(reg2, reg14, cospi_28_64, cospi_4_64, reg2, reg14); + VP9_DOTP_CONST_PAIR(reg10, reg6, cospi_12_64, cospi_20_64, reg10, reg6); + LSX_BUTTERFLY_4_H(reg2, reg14, reg6, reg10, loc0, loc1, reg14, reg2); + VP9_DOTP_CONST_PAIR(reg14, reg2, cospi_16_64, cospi_16_64, loc2, loc3); + VP9_DOTP_CONST_PAIR(reg0, reg8, cospi_16_64, cospi_16_64, reg0, reg8); + VP9_DOTP_CONST_PAIR(reg4, reg12, cospi_24_64, cospi_8_64, reg4, reg12); + LSX_BUTTERFLY_4_H(reg8, reg0, reg4, reg12, reg2, reg6, reg10, reg14); + + reg0 = __lsx_vsub_h(reg2, loc1); + reg2 = __lsx_vadd_h(reg2, loc1); + reg12 = __lsx_vsub_h(reg14, loc0); + reg14 = __lsx_vadd_h(reg14, loc0); + reg4 = __lsx_vsub_h(reg6, loc3); + reg6 = __lsx_vadd_h(reg6, loc3); + reg8 = __lsx_vsub_h(reg10, loc2); + reg10 = __lsx_vadd_h(reg10, loc2); + + /* stage2 */ + VP9_DOTP_CONST_PAIR(reg1, reg15, cospi_30_64, cospi_2_64, reg1, reg15); + VP9_DOTP_CONST_PAIR(reg9, reg7, cospi_14_64, cospi_18_64, loc2, loc3); + + reg9 = __lsx_vsub_h(reg1, loc2); + reg1 = __lsx_vadd_h(reg1, loc2); + reg7 = __lsx_vsub_h(reg15, loc3); + reg15 = __lsx_vadd_h(reg15, loc3); + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_22_64, cospi_10_64, reg5, reg11); + VP9_DOTP_CONST_PAIR(reg13, reg3, cospi_6_64, cospi_26_64, loc0, loc1); + LSX_BUTTERFLY_4_H(loc0, loc1, reg11, reg5, reg13, reg3, reg11, reg5); + + loc1 = __lsx_vadd_h(reg15, reg3); + reg3 = __lsx_vsub_h(reg15, reg3); + loc2 = __lsx_vadd_h(reg2, loc1); + reg15 = __lsx_vsub_h(reg2, loc1); + + loc1 = __lsx_vadd_h(reg1, reg13); + reg13 = __lsx_vsub_h(reg1, reg13); + loc0 = __lsx_vadd_h(reg0, loc1); + loc1 = __lsx_vsub_h(reg0, loc1); + tmp6 = loc0; + tmp7 = loc1; + reg0 = loc2; + + VP9_DOTP_CONST_PAIR(reg7, reg9, cospi_24_64, cospi_8_64, reg7, reg9); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg5), __lsx_vneg_h(reg11), cospi_8_64, + cospi_24_64, reg5, reg11); + + loc0 = __lsx_vadd_h(reg9, reg5); + reg5 = __lsx_vsub_h(reg9, reg5); + reg2 = __lsx_vadd_h(reg6, loc0); + reg1 = __lsx_vsub_h(reg6, loc0); + + loc0 = __lsx_vadd_h(reg7, reg11); + reg11 = __lsx_vsub_h(reg7, reg11); + loc1 = __lsx_vadd_h(reg4, loc0); + loc2 = __lsx_vsub_h(reg4, loc0); + + tmp5 = loc1; + + VP9_DOTP_CONST_PAIR(reg5, reg11, cospi_16_64, cospi_16_64, reg5, reg11); + LSX_BUTTERFLY_4_H(reg8, reg10, reg11, reg5, loc0, reg4, reg9, loc1); + + reg10 = loc0; + reg11 = loc1; + + VP9_DOTP_CONST_PAIR(reg3, reg13, cospi_16_64, cospi_16_64, reg3, reg13); + LSX_BUTTERFLY_4_H(reg12, reg14, reg13, reg3, reg8, reg6, reg7, reg5); + reg13 = loc2; + + /* Transpose and store the output */ + reg12 = tmp5; + reg14 = tmp6; + reg3 = tmp7; + + /* transpose block */ + LSX_TRANSPOSE8x8_H(reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14, + reg0, reg2, reg4, reg6, reg8, reg10, reg12, reg14); + + __lsx_vst(reg0, output, 32*0); + __lsx_vst(reg2, output, 32*1); + __lsx_vst(reg4, output, 32*2); + __lsx_vst(reg6, output, 32*3); + __lsx_vst(reg8, output, 32*4); + __lsx_vst(reg10, output, 32*5); + __lsx_vst(reg12, output, 32*6); + __lsx_vst(reg14, output, 32*7); + + /* transpose block */ + LSX_TRANSPOSE8x8_H(reg3, reg13, reg11, reg5, reg7, reg9, reg1, reg15, + reg3, reg13, reg11, reg5, reg7, reg9, reg1, reg15); + + offset = output + 8; + __lsx_vst(reg3, offset, 32*0); + __lsx_vst(reg13, offset, 32*1); + __lsx_vst(reg11, offset, 32*2); + __lsx_vst(reg5, offset, 32*3); + + offset = output + 8 + 4 * 16; + __lsx_vst(reg7, offset, 32*0); + __lsx_vst(reg9, offset, 32*1); + __lsx_vst(reg1, offset, 32*2); + __lsx_vst(reg15, offset, 32*3); +} + +static void vp9_idct16x16_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + uint8_t i; + int16_t out; + __m128i vec, res0, res1, res2, res3, res4, res5, res6, res7; + __m128i dst0, dst1, dst2, dst3, tmp0, tmp1, tmp2, tmp3; + int32_t stride2 = dst_stride << 1; + int32_t stride3 = stride2 + dst_stride; + int32_t stride4 = stride2 << 1; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO(out, 6); + input[0] = 0; + vec = __lsx_vreplgr2vr_h(out); + + for (i = 4; i--;) { + dst0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, stride2, dst1, dst2); + dst3 = __lsx_vldx(dst, stride3); + VP9_UNPCK_UB_SH(dst0, res4, res0); + VP9_UNPCK_UB_SH(dst1, res5, res1); + VP9_UNPCK_UB_SH(dst2, res6, res2); + VP9_UNPCK_UB_SH(dst3, res7, res3); + DUP4_ARG2(__lsx_vadd_h, res0, vec, res1, vec, res2, vec, res3, vec, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vadd_h, res4, vec, res5, vec, res6, vec, res7, vec, + res4, res5, res6, res7); + DUP4_ARG1(__lsx_vclip255_h, res0, res1, res2, res3, + res0, res1, res2, res3); + DUP4_ARG1(__lsx_vclip255_h, res4, res5, res6, res7, + res4, res5, res6, res7); + DUP4_ARG2(__lsx_vpickev_b, res4, res0, res5, res1, res6, + res2, res7, res3, tmp0, tmp1, tmp2, tmp3); + __lsx_vst(tmp0, dst, 0); + __lsx_vstx(tmp1, dst, dst_stride); + __lsx_vstx(tmp2, dst, stride2); + __lsx_vstx(tmp3, dst, stride3); + dst += stride4; + } +} + +static void vp9_idct16x16_10_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[16 * 16] ALLOC_ALIGNED(16); + int16_t *out = out_arr; + __m128i zero = __lsx_vldi(0); + + /* transform rows */ + vp9_idct16_1d_columns_lsx(input, out); + + /* short case just considers top 4 rows as valid output */ + out += 4 * 16; + for (i = 3; i--;) { + __lsx_vst(zero, out, 0); + __lsx_vst(zero, out, 16); + __lsx_vst(zero, out, 32); + __lsx_vst(zero, out, 48); + __lsx_vst(zero, out, 64); + __lsx_vst(zero, out, 80); + __lsx_vst(zero, out, 96); + __lsx_vst(zero, out, 112); + out += 64; + } + + out = out_arr; + + /* transform columns */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_addblk_lsx((out + (i << 3)), (dst + (i << 3)), + dst_stride); + } +} + +static void vp9_idct16x16_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[16 * 16] ALLOC_ALIGNED(16); + int16_t *out = out_arr; + + /* transform rows */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_lsx((input + (i << 3)), (out + (i << 7))); + } + + /* transform columns */ + for (i = 0; i < 2; i++) { + /* process 8 * 16 block */ + vp9_idct16_1d_columns_addblk_lsx((out + (i << 3)), (dst + (i << 3)), + dst_stride); + } +} + +static void vp9_idct_butterfly_transpose_store(int16_t *tmp_buf, + int16_t *tmp_eve_buf, + int16_t *tmp_odd_buf, + int16_t *dst) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i m0, m1, m2, m3, m4, m5, m6, m7, n0, n1, n2, n3, n4, n5, n6, n7; + + /* FINAL BUTTERFLY : Dependency on Even & Odd */ + vec0 = __lsx_vld(tmp_odd_buf, 0); + vec1 = __lsx_vld(tmp_odd_buf, 9 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 14 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 6 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 0); + loc1 = __lsx_vld(tmp_eve_buf, 8 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 4 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 12 * 16); + + DUP4_ARG2(__lsx_vadd_h,loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m0, m4, m2, m6); + + #define SUB(a, b) __lsx_vsub_h(a, b) + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 31 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 23 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 27 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 19 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 4 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 13 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 10 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 3 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 2 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 10 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 6 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 14 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m1, m5, m3, m7); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 29 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 21 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 25 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 17 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 2 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 11 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 12 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 7 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 1 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 9 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 5 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 13 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n0, n4, n2, n6); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 30 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 22 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 26 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 18 * 16); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 5 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 15 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 8 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 1 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 3 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 11 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 7 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 15 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n1, n5, n3, n7); + + __lsx_vst(SUB(loc0, vec3), tmp_buf, 28 * 16); + __lsx_vst(SUB(loc1, vec2), tmp_buf, 20 * 16); + __lsx_vst(SUB(loc2, vec1), tmp_buf, 24 * 16); + __lsx_vst(SUB(loc3, vec0), tmp_buf, 16 * 16); + + /* Transpose : 16 vectors */ + /* 1st & 2nd 8x8 */ + LSX_TRANSPOSE8x8_H(m0, n0, m1, n1, m2, n2, m3, n3, + m0, n0, m1, n1, m2, n2, m3, n3); + __lsx_vst(m0, dst, 0); + __lsx_vst(n0, dst, 32 * 2); + __lsx_vst(m1, dst, 32 * 4); + __lsx_vst(n1, dst, 32 * 6); + __lsx_vst(m2, dst, 32 * 8); + __lsx_vst(n2, dst, 32 * 10); + __lsx_vst(m3, dst, 32 * 12); + __lsx_vst(n3, dst, 32 * 14); + + LSX_TRANSPOSE8x8_H(m4, n4, m5, n5, m6, n6, m7, n7, + m4, n4, m5, n5, m6, n6, m7, n7); + + __lsx_vst(m4, dst, 16); + __lsx_vst(n4, dst, 16 + 32 * 2); + __lsx_vst(m5, dst, 16 + 32 * 4); + __lsx_vst(n5, dst, 16 + 32 * 6); + __lsx_vst(m6, dst, 16 + 32 * 8); + __lsx_vst(n6, dst, 16 + 32 * 10); + __lsx_vst(m7, dst, 16 + 32 * 12); + __lsx_vst(n7, dst, 16 + 32 * 14); + + /* 3rd & 4th 8x8 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 16, tmp_buf, 16 * 17, + tmp_buf, 16 * 18, tmp_buf, 16 * 19, m0, n0, m1, n1); + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 20, tmp_buf, 16 * 21, + tmp_buf, 16 * 22, tmp_buf, 16 * 23, m2, n2, m3, n3); + + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 24, tmp_buf, 16 * 25, + tmp_buf, 16 * 26, tmp_buf, 16 * 27, m4, n4, m5, n5); + DUP4_ARG2(__lsx_vld, tmp_buf, 16 * 28, tmp_buf, 16 * 29, + tmp_buf, 16 * 30, tmp_buf, 16 * 31, m6, n6, m7, n7); + + LSX_TRANSPOSE8x8_H(m0, n0, m1, n1, m2, n2, m3, n3, + m0, n0, m1, n1, m2, n2, m3, n3); + + __lsx_vst(m0, dst, 32); + __lsx_vst(n0, dst, 32 + 32 * 2); + __lsx_vst(m1, dst, 32 + 32 * 4); + __lsx_vst(n1, dst, 32 + 32 * 6); + __lsx_vst(m2, dst, 32 + 32 * 8); + __lsx_vst(n2, dst, 32 + 32 * 10); + __lsx_vst(m3, dst, 32 + 32 * 12); + __lsx_vst(n3, dst, 32 + 32 * 14); + + LSX_TRANSPOSE8x8_H(m4, n4, m5, n5, m6, n6, m7, n7, + m4, n4, m5, n5, m6, n6, m7, n7); + + __lsx_vst(m4, dst, 48); + __lsx_vst(n4, dst, 48 + 32 * 2); + __lsx_vst(m5, dst, 48 + 32 * 4); + __lsx_vst(n5, dst, 48 + 32 * 6); + __lsx_vst(m6, dst, 48 + 32 * 8); + __lsx_vst(n6, dst, 48 + 32 * 10); + __lsx_vst(m7, dst, 48 + 32 * 12); + __lsx_vst(n7, dst, 48 + 32 * 14); +} + +static void vp9_idct8x32_column_even_process_store(int16_t *tmp_buf, + int16_t *tmp_eve_buf) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; + __m128i stp0, stp1, stp2, stp3, stp4, stp5, stp6, stp7; + __m128i zero = __lsx_vldi(0); + + /* Even stage 1 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 0, tmp_buf, 32 * 8, + tmp_buf, 32 * 16, tmp_buf, 32 * 24, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_buf, 32 * 32, tmp_buf, 32 * 40, + tmp_buf, 32 * 48, tmp_buf, 32 * 56, reg4, reg5, reg6, reg7); + + __lsx_vst(zero, tmp_buf, 0); + __lsx_vst(zero, tmp_buf, 32 * 8); + __lsx_vst(zero, tmp_buf, 32 * 16); + __lsx_vst(zero, tmp_buf, 32 * 24); + __lsx_vst(zero, tmp_buf, 32 * 32); + __lsx_vst(zero, tmp_buf, 32 * 40); + __lsx_vst(zero, tmp_buf, 32 * 48); + __lsx_vst(zero, tmp_buf, 32 * 56); + + tmp_buf += (2 * 32); + + VP9_DOTP_CONST_PAIR(reg1, reg7, cospi_28_64, cospi_4_64, reg1, reg7); + VP9_DOTP_CONST_PAIR(reg5, reg3, cospi_12_64, cospi_20_64, reg5, reg3); + LSX_BUTTERFLY_4_H(reg1, reg7, reg3, reg5, vec1, vec3, vec2, vec0); + VP9_DOTP_CONST_PAIR(vec2, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + + loc1 = vec3; + loc0 = vec1; + + VP9_DOTP_CONST_PAIR(reg0, reg4, cospi_16_64, cospi_16_64, reg0, reg4); + VP9_DOTP_CONST_PAIR(reg2, reg6, cospi_24_64, cospi_8_64, reg2, reg6); + LSX_BUTTERFLY_4_H(reg4, reg0, reg2, reg6, vec1, vec3, vec2, vec0); + LSX_BUTTERFLY_4_H(vec0, vec1, loc1, loc0, stp3, stp0, stp7, stp4); + LSX_BUTTERFLY_4_H(vec2, vec3, loc3, loc2, stp2, stp1, stp6, stp5); + + /* Even stage 2 */ + /* Load 8 */ + DUP4_ARG2(__lsx_vld, tmp_buf, 0, tmp_buf, 32 * 8, + tmp_buf, 32 * 16, tmp_buf, 32 * 24, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_buf, 32 * 32, tmp_buf, 32 * 40, + tmp_buf, 32 * 48, tmp_buf, 32 * 56, reg4, reg5, reg6, reg7); + + __lsx_vst(zero, tmp_buf, 0); + __lsx_vst(zero, tmp_buf, 32 * 8); + __lsx_vst(zero, tmp_buf, 32 * 16); + __lsx_vst(zero, tmp_buf, 32 * 24); + __lsx_vst(zero, tmp_buf, 32 * 32); + __lsx_vst(zero, tmp_buf, 32 * 40); + __lsx_vst(zero, tmp_buf, 32 * 48); + __lsx_vst(zero, tmp_buf, 32 * 56); + + VP9_DOTP_CONST_PAIR(reg0, reg7, cospi_30_64, cospi_2_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_14_64, cospi_18_64, reg4, reg3); + VP9_DOTP_CONST_PAIR(reg2, reg5, cospi_22_64, cospi_10_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg6, reg1, cospi_6_64, cospi_26_64, reg6, reg1); + + vec0 = __lsx_vadd_h(reg0, reg4); + reg0 = __lsx_vsub_h(reg0, reg4); + reg4 = __lsx_vadd_h(reg6, reg2); + reg6 = __lsx_vsub_h(reg6, reg2); + reg2 = __lsx_vadd_h(reg1, reg5); + reg1 = __lsx_vsub_h(reg1, reg5); + reg5 = __lsx_vadd_h(reg7, reg3); + reg7 = __lsx_vsub_h(reg7, reg3); + reg3 = vec0; + + vec1 = reg2; + reg2 = __lsx_vadd_h(reg3, reg4); + reg3 = __lsx_vsub_h(reg3, reg4); + reg4 = __lsx_vsub_h(reg5, vec1); + reg5 = __lsx_vadd_h(reg5, vec1); + + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_24_64, cospi_8_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(__lsx_vneg_h(reg6), reg1, cospi_24_64, cospi_8_64, + reg6, reg1); + + vec0 = __lsx_vsub_h(reg0, reg6); + reg0 = __lsx_vadd_h(reg0, reg6); + vec1 = __lsx_vsub_h(reg7, reg1); + reg7 = __lsx_vadd_h(reg7, reg1); + + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, reg6, reg1); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_16_64, cospi_16_64, reg3, reg4); + + /* Even stage 3 : Dependency on Even stage 1 & Even stage 2 */ + /* Store 8 */ + LSX_BUTTERFLY_4_H(stp0, stp1, reg7, reg5, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 0); + __lsx_vst(loc3, tmp_eve_buf, 16); + __lsx_vst(loc2, tmp_eve_buf, 14 * 16); + __lsx_vst(loc0, tmp_eve_buf, 14 * 16 + 16); + LSX_BUTTERFLY_4_H(stp2, stp3, reg4, reg1, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 2 * 16); + __lsx_vst(loc3, tmp_eve_buf, 2 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 12 * 16); + __lsx_vst(loc0, tmp_eve_buf, 12 * 16 + 16); + + /* Store 8 */ + LSX_BUTTERFLY_4_H(stp4, stp5, reg6, reg3, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 4 * 16); + __lsx_vst(loc3, tmp_eve_buf, 4 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 10 * 16); + __lsx_vst(loc0, tmp_eve_buf, 10 * 16 + 16); + + LSX_BUTTERFLY_4_H(stp6, stp7, reg2, reg0, loc1, loc3, loc2, loc0); + __lsx_vst(loc1, tmp_eve_buf, 6 * 16); + __lsx_vst(loc3, tmp_eve_buf, 6 * 16 + 16); + __lsx_vst(loc2, tmp_eve_buf, 8 * 16); + __lsx_vst(loc0, tmp_eve_buf, 8 * 16 + 16); +} + +static void vp9_idct8x32_column_odd_process_store(int16_t *tmp_buf, + int16_t *tmp_odd_buf) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7; + __m128i zero = __lsx_vldi(0); + + /* Odd stage 1 */ + reg0 = __lsx_vld(tmp_buf, 64); + reg1 = __lsx_vld(tmp_buf, 7 * 64); + reg2 = __lsx_vld(tmp_buf, 9 * 64); + reg3 = __lsx_vld(tmp_buf, 15 * 64); + reg4 = __lsx_vld(tmp_buf, 17 * 64); + reg5 = __lsx_vld(tmp_buf, 23 * 64); + reg6 = __lsx_vld(tmp_buf, 25 * 64); + reg7 = __lsx_vld(tmp_buf, 31 * 64); + + __lsx_vst(zero, tmp_buf, 64); + __lsx_vst(zero, tmp_buf, 7 * 64); + __lsx_vst(zero, tmp_buf, 9 * 64); + __lsx_vst(zero, tmp_buf, 15 * 64); + __lsx_vst(zero, tmp_buf, 17 * 64); + __lsx_vst(zero, tmp_buf, 23 * 64); + __lsx_vst(zero, tmp_buf, 25 * 64); + __lsx_vst(zero, tmp_buf, 31 * 64); + + VP9_DOTP_CONST_PAIR(reg0, reg7, cospi_31_64, cospi_1_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg4, reg3, cospi_15_64, cospi_17_64, reg3, reg4); + VP9_DOTP_CONST_PAIR(reg2, reg5, cospi_23_64, cospi_9_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg6, reg1, cospi_7_64, cospi_25_64, reg1, reg6); + + vec0 = __lsx_vadd_h(reg0, reg3); + reg0 = __lsx_vsub_h(reg0, reg3); + reg3 = __lsx_vadd_h(reg7, reg4); + reg7 = __lsx_vsub_h(reg7, reg4); + reg4 = __lsx_vadd_h(reg1, reg2); + reg1 = __lsx_vsub_h(reg1, reg2); + reg2 = __lsx_vadd_h(reg6, reg5); + reg6 = __lsx_vsub_h(reg6, reg5); + reg5 = vec0; + + /* 4 Stores */ + DUP2_ARG2(__lsx_vadd_h, reg5, reg4, reg3, reg2, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 4 * 16); + __lsx_vst(vec1, tmp_odd_buf, 4 * 16 + 16); + DUP2_ARG2(__lsx_vsub_h, reg5, reg4, reg3, reg2, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_24_64, cospi_8_64, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 0); + __lsx_vst(vec1, tmp_odd_buf, 16); + + /* 4 Stores */ + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_28_64, cospi_4_64, reg0, reg7); + VP9_DOTP_CONST_PAIR(reg6, reg1, -cospi_4_64, cospi_28_64, reg1, reg6); + LSX_BUTTERFLY_4_H(reg0, reg7, reg6, reg1, vec0, vec1, vec2, vec3); + __lsx_vst(vec0, tmp_odd_buf, 6 * 16); + __lsx_vst(vec1, tmp_odd_buf, 6 * 16 + 16); + VP9_DOTP_CONST_PAIR(vec2, vec3, cospi_24_64, cospi_8_64, vec2, vec3); + __lsx_vst(vec2, tmp_odd_buf, 2 * 16); + __lsx_vst(vec3, tmp_odd_buf, 2 * 16 + 16); + + /* Odd stage 2 */ + /* 8 loads */ + reg0 = __lsx_vld(tmp_buf, 3 * 64); + reg1 = __lsx_vld(tmp_buf, 5 * 64); + reg2 = __lsx_vld(tmp_buf, 11 * 64); + reg3 = __lsx_vld(tmp_buf, 13 * 64); + reg4 = __lsx_vld(tmp_buf, 19 * 64); + reg5 = __lsx_vld(tmp_buf, 21 * 64); + reg6 = __lsx_vld(tmp_buf, 27 * 64); + reg7 = __lsx_vld(tmp_buf, 29 * 64); + + __lsx_vst(zero, tmp_buf, 3 * 64); + __lsx_vst(zero, tmp_buf, 5 * 64); + __lsx_vst(zero, tmp_buf, 11 * 64); + __lsx_vst(zero, tmp_buf, 13 * 64); + __lsx_vst(zero, tmp_buf, 19 * 64); + __lsx_vst(zero, tmp_buf, 21 * 64); + __lsx_vst(zero, tmp_buf, 27 * 64); + __lsx_vst(zero, tmp_buf, 29 * 64); + + VP9_DOTP_CONST_PAIR(reg1, reg6, cospi_27_64, cospi_5_64, reg1, reg6); + VP9_DOTP_CONST_PAIR(reg5, reg2, cospi_11_64, cospi_21_64, reg2, reg5); + VP9_DOTP_CONST_PAIR(reg3, reg4, cospi_19_64, cospi_13_64, reg3, reg4); + VP9_DOTP_CONST_PAIR(reg7, reg0, cospi_3_64, cospi_29_64, reg0, reg7); + + /* 4 Stores */ + DUP4_ARG2(__lsx_vsub_h,reg1, reg2, reg6, reg5, reg0, reg3, reg7, reg4, + vec0, vec1, vec2, vec3); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_12_64, cospi_20_64, loc0, loc1); + VP9_DOTP_CONST_PAIR(vec3, vec2, -cospi_20_64, cospi_12_64, loc2, loc3); + LSX_BUTTERFLY_4_H(loc2, loc3, loc1, loc0, vec0, vec1, vec3, vec2); + __lsx_vst(vec0, tmp_odd_buf, 12 * 16); + __lsx_vst(vec1, tmp_odd_buf, 12 * 16 + 3 * 16); + VP9_DOTP_CONST_PAIR(vec3, vec2, -cospi_8_64, cospi_24_64, vec0, vec1); + __lsx_vst(vec0, tmp_odd_buf, 10 * 16); + __lsx_vst(vec1, tmp_odd_buf, 10 * 16 + 16); + + /* 4 Stores */ + DUP4_ARG2(__lsx_vadd_h, reg0, reg3, reg1, reg2, reg5, reg6, reg4, reg7, + vec0, vec1, vec2, vec3); + LSX_BUTTERFLY_4_H(vec0, vec3, vec2, vec1, reg0, reg1, reg3, reg2); + __lsx_vst(reg0, tmp_odd_buf, 13 * 16); + __lsx_vst(reg1, tmp_odd_buf, 13 * 16 + 16); + VP9_DOTP_CONST_PAIR(reg3, reg2, -cospi_8_64, cospi_24_64, + reg0, reg1); + __lsx_vst(reg0, tmp_odd_buf, 8 * 16); + __lsx_vst(reg1, tmp_odd_buf, 8 * 16 + 16); + + /* Odd stage 3 : Dependency on Odd stage 1 & Odd stage 2 */ + /* Load 8 & Store 8 */ + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 0, tmp_odd_buf, 16, + tmp_odd_buf, 32, tmp_odd_buf, 48, reg0, reg1, reg2, reg3); + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 8 * 16, tmp_odd_buf, 8 * 16 + 16, + tmp_odd_buf, 8 * 16 + 32, tmp_odd_buf, 8 * 16 + 48, + reg4, reg5, reg6, reg7); + + DUP4_ARG2(__lsx_vadd_h, reg0, reg4, reg1, reg5, reg2, reg6, reg3, reg7, + loc0, loc1, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 0); + __lsx_vst(loc1, tmp_odd_buf, 16); + __lsx_vst(loc2, tmp_odd_buf, 32); + __lsx_vst(loc3, tmp_odd_buf, 48); + DUP2_ARG2(__lsx_vsub_h, reg0, reg4, reg1, reg5, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc0, loc1); + + DUP2_ARG2(__lsx_vsub_h, reg2, reg6, reg3, reg7, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 8 * 16); + __lsx_vst(loc1, tmp_odd_buf, 8 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 8 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 8 * 16 + 48); + + /* Load 8 & Store 8 */ + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 4 * 16, tmp_odd_buf, 4 * 16 + 16, + tmp_odd_buf, 4 * 16 + 32, tmp_odd_buf, 4 * 16 + 48, + reg1, reg2, reg0, reg3); + DUP4_ARG2(__lsx_vld, tmp_odd_buf, 12 * 16, tmp_odd_buf, 12 * 16 + 16, + tmp_odd_buf, 12 * 16 + 32, tmp_odd_buf, 12 * 16 + 48, + reg4, reg5, reg6, reg7); + + DUP4_ARG2(__lsx_vadd_h, reg0, reg4, reg1, reg5, reg2, reg6, reg3, reg7, + loc0, loc1, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 4 * 16); + __lsx_vst(loc1, tmp_odd_buf, 4 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 4 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 4 * 16 + 48); + + DUP2_ARG2(__lsx_vsub_h, reg0, reg4, reg3, reg7, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc0, loc1); + + DUP2_ARG2(__lsx_vsub_h, reg1, reg5, reg2, reg6, vec0, vec1); + VP9_DOTP_CONST_PAIR(vec1, vec0, cospi_16_64, cospi_16_64, loc2, loc3); + __lsx_vst(loc0, tmp_odd_buf, 12 * 16); + __lsx_vst(loc1, tmp_odd_buf, 12 * 16 + 16); + __lsx_vst(loc2, tmp_odd_buf, 12 * 16 + 32); + __lsx_vst(loc3, tmp_odd_buf, 12 * 16 + 48); +} + +static void vp9_idct8x32_column_butterfly_addblk(int16_t *tmp_eve_buf, + int16_t *tmp_odd_buf, + uint8_t *dst, + int32_t dst_stride) +{ + __m128i vec0, vec1, vec2, vec3, loc0, loc1, loc2, loc3; + __m128i m0, m1, m2, m3, m4, m5, m6, m7, n0, n1, n2, n3, n4, n5, n6, n7; + + /* FINAL BUTTERFLY : Dependency on Even & Odd */ + vec0 = __lsx_vld(tmp_odd_buf, 0); + vec1 = __lsx_vld(tmp_odd_buf, 9 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 14 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 6 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 0); + loc1 = __lsx_vld(tmp_eve_buf, 8 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 4 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 12 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m0, m4, m2, m6); + DUP4_ARG2(__lsx_vsrari_h, m0, 6, m2, 6, m4, 6, m6, 6, m0, m2, m4, m6); + VP9_ADDBLK_ST8x4_UB(dst, (4 * dst_stride), m0, m2, m4, m6); + + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m6, m2, m4, m0); + DUP4_ARG2(__lsx_vsrari_h, m0, 6, m2, 6, m4, 6, m6, 6, m0, m2, m4, m6); + VP9_ADDBLK_ST8x4_UB((dst + 19 * dst_stride), (4 * dst_stride), + m0, m2, m4, m6); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 4 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 13 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 10 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 3 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 2 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 10 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 6 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 14 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m1, m5, m3, m7); + DUP4_ARG2(__lsx_vsrari_h, m1, 6, m3, 6, m5, 6, m7, 6, m1, m3, m5, m7); + VP9_ADDBLK_ST8x4_UB((dst + 2 * dst_stride), (4 * dst_stride), + m1, m3, m5, m7); + + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + m7, m3, m5, m1); + DUP4_ARG2(__lsx_vsrari_h, m1, 6, m3, 6, m5, 6, m7, 6, m1, m3, m5, m7); + VP9_ADDBLK_ST8x4_UB((dst + 17 * dst_stride), (4 * dst_stride), + m1, m3, m5, m7); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 2 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 11 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 12 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 7 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 1 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 9 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 5 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 13 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n0, n4, n2, n6); + DUP4_ARG2(__lsx_vsrari_h, n0, 6, n2, 6, n4, 6, n6, 6, n0, n2, n4, n6); + VP9_ADDBLK_ST8x4_UB((dst + 1 * dst_stride), (4 * dst_stride), + n0, n2, n4, n6); + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n6, n2, n4, n0); + DUP4_ARG2(__lsx_vsrari_h, n0, 6, n2, 6, n4, 6, n6, 6, n0, n2, n4, n6); + VP9_ADDBLK_ST8x4_UB((dst + 18 * dst_stride), (4 * dst_stride), + n0, n2, n4, n6); + + /* Load 8 & Store 8 */ + vec0 = __lsx_vld(tmp_odd_buf, 5 * 16); + vec1 = __lsx_vld(tmp_odd_buf, 15 * 16); + vec2 = __lsx_vld(tmp_odd_buf, 8 * 16); + vec3 = __lsx_vld(tmp_odd_buf, 1 * 16); + loc0 = __lsx_vld(tmp_eve_buf, 3 * 16); + loc1 = __lsx_vld(tmp_eve_buf, 11 * 16); + loc2 = __lsx_vld(tmp_eve_buf, 7 * 16); + loc3 = __lsx_vld(tmp_eve_buf, 15 * 16); + + DUP4_ARG2(__lsx_vadd_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n1, n5, n3, n7); + DUP4_ARG2(__lsx_vsrari_h, n1, 6, n3, 6, n5, 6, n7, 6, n1, n3, n5, n7); + VP9_ADDBLK_ST8x4_UB((dst + 3 * dst_stride), (4 * dst_stride), + n1, n3, n5, n7); + DUP4_ARG2(__lsx_vsub_h, loc0, vec3, loc1, vec2, loc2, vec1, loc3, vec0, + n7, n3, n5, n1); + DUP4_ARG2(__lsx_vsrari_h, n1, 6, n3, 6, n5, 6, n7, 6, n1, n3, n5, n7); + VP9_ADDBLK_ST8x4_UB((dst + 16 * dst_stride), (4 * dst_stride), + n1, n3, n5, n7); +} + +static void vp9_idct8x32_1d_columns_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int16_t tmp_odd_buf[16 * 8] ALLOC_ALIGNED(16); + int16_t tmp_eve_buf[16 * 8] ALLOC_ALIGNED(16); + + vp9_idct8x32_column_even_process_store(input, &tmp_eve_buf[0]); + vp9_idct8x32_column_odd_process_store(input, &tmp_odd_buf[0]); + vp9_idct8x32_column_butterfly_addblk(&tmp_eve_buf[0], &tmp_odd_buf[0], + dst, dst_stride); +} + +static void vp9_idct8x32_1d_columns_lsx(int16_t *input, int16_t *output, + int16_t *tmp_buf) +{ + int16_t tmp_odd_buf[16 * 8] ALLOC_ALIGNED(16); + int16_t tmp_eve_buf[16 * 8] ALLOC_ALIGNED(16); + + vp9_idct8x32_column_even_process_store(input, &tmp_eve_buf[0]); + vp9_idct8x32_column_odd_process_store(input, &tmp_odd_buf[0]); + vp9_idct_butterfly_transpose_store(tmp_buf, &tmp_eve_buf[0], + &tmp_odd_buf[0], output); +} + +static void vp9_idct32x32_1_add_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out; + uint8_t *dst_tmp = dst + dst_stride; + __m128i zero = __lsx_vldi(0); + __m128i dst0, dst1, dst2, dst3, tmp0, tmp1, tmp2, tmp3; + __m128i res0, res1, res2, res3, res4, res5, res6, res7, vec; + + out = ROUND_POWER_OF_TWO((input[0] * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO((out * cospi_16_64), VP9_DCT_CONST_BITS); + out = ROUND_POWER_OF_TWO(out, 6); + input[0] = 0; + + vec = __lsx_vreplgr2vr_h(out); + + for (i = 16; i--;) { + DUP2_ARG2(__lsx_vld, dst, 0, dst, 16, dst0, dst1); + DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst2, dst3); + + DUP4_ARG2(__lsx_vilvl_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vilvh_b, zero, dst0, zero, dst1, zero, dst2, zero, dst3, + res4, res5, res6, res7); + DUP4_ARG2(__lsx_vadd_h, res0, vec, res1, vec, res2, vec, res3, vec, + res0, res1, res2, res3); + DUP4_ARG2(__lsx_vadd_h, res4, vec, res5, vec, res6, vec, res7, vec, + res4, res5, res6, res7); + DUP4_ARG1(__lsx_vclip255_h, res0, res1, res2, res3, res0, res1, res2, res3); + DUP4_ARG1(__lsx_vclip255_h, res4, res5, res6, res7, res4, res5, res6, res7); + DUP4_ARG2(__lsx_vpickev_b, res4, res0, res5, res1, res6, res2, res7, res3, + tmp0, tmp1, tmp2, tmp3); + + __lsx_vst(tmp0, dst, 0); + __lsx_vst(tmp1, dst, 16); + __lsx_vst(tmp2, dst_tmp, 0); + __lsx_vst(tmp3, dst_tmp, 16); + dst = dst_tmp + dst_stride; + dst_tmp = dst + dst_stride; + } +} + +static void vp9_idct32x32_34_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[32 * 32] ALLOC_ALIGNED(16); + int16_t *out_ptr = out_arr; + int16_t tmp_buf[8 * 32] ALLOC_ALIGNED(16); + __m128i zero = __lsx_vldi(0); + + for (i = 16; i--;) { + __lsx_vst(zero, out_ptr, 0); + __lsx_vst(zero, out_ptr, 16); + __lsx_vst(zero, out_ptr, 32); + __lsx_vst(zero, out_ptr, 48); + __lsx_vst(zero, out_ptr, 64); + __lsx_vst(zero, out_ptr, 80); + __lsx_vst(zero, out_ptr, 96); + __lsx_vst(zero, out_ptr, 112); + out_ptr += 64; + } + + out_ptr = out_arr; + + /* process 8*32 block */ + vp9_idct8x32_1d_columns_lsx(input, out_ptr, &tmp_buf[0]); + + /* transform columns */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_addblk_lsx((out_ptr + (i << 3)), + (dst + (i << 3)), dst_stride); + } +} + +static void vp9_idct32x32_colcol_addblk_lsx(int16_t *input, uint8_t *dst, + int32_t dst_stride) +{ + int32_t i; + int16_t out_arr[32 * 32] ALLOC_ALIGNED(16); + int16_t *out_ptr = out_arr; + int16_t tmp_buf[8 * 32] ALLOC_ALIGNED(16); + + /* transform rows */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_lsx((input + (i << 3)), (out_ptr + (i << 8)), + &tmp_buf[0]); + } + + /* transform columns */ + for (i = 0; i < 4; i++) { + /* process 8*32 block */ + vp9_idct8x32_1d_columns_addblk_lsx((out_ptr + (i << 3)), + (dst + (i << 3)), dst_stride); + } +} + +void ff_idct_idct_8x8_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + vp9_idct8x8_1_add_lsx(block, dst, stride); + } + else if (eob <= 12) { + vp9_idct8x8_12_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct8x8_colcol_addblk_lsx(block, dst, stride); + } +} + +void ff_idct_idct_16x16_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + /* DC only DCT coefficient. */ + vp9_idct16x16_1_add_lsx(block, dst, stride); + } + else if (eob <= 10) { + vp9_idct16x16_10_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct16x16_colcol_addblk_lsx(block, dst, stride); + } +} + +void ff_idct_idct_32x32_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob) +{ + if (eob == 1) { + vp9_idct32x32_1_add_lsx(block, dst, stride); + } + else if (eob <= 34) { + vp9_idct32x32_34_colcol_addblk_lsx(block, dst, stride); + } + else { + vp9_idct32x32_colcol_addblk_lsx(block, dst, stride); + } +} diff --git a/libavcodec/loongarch/vp9_intra_lsx.c b/libavcodec/loongarch/vp9_intra_lsx.c new file mode 100644 index 0000000000..d3f32646f3 --- /dev/null +++ b/libavcodec/loongarch/vp9_intra_lsx.c @@ -0,0 +1,653 @@ +/* + * 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 "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" + +#define LSX_ST_8(_dst0, _dst1, _dst2, _dst3, _dst4, \ + _dst5, _dst6, _dst7, _dst, _stride, \ + _stride2, _stride3, _stride4) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vstx(_dst1, _dst, _stride); \ + __lsx_vstx(_dst2, _dst, _stride2); \ + __lsx_vstx(_dst3, _dst, _stride3); \ + _dst += _stride4; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vstx(_dst5, _dst, _stride); \ + __lsx_vstx(_dst6, _dst, _stride2); \ + __lsx_vstx(_dst7, _dst, _stride3); \ +} + +#define LSX_ST_8X16(_dst0, _dst1, _dst2, _dst3, _dst4, \ + _dst5, _dst6, _dst7, _dst, _stride) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vst(_dst0, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst1, _dst, 0); \ + __lsx_vst(_dst1, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst2, _dst, 0); \ + __lsx_vst(_dst2, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst3, _dst, 0); \ + __lsx_vst(_dst3, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vst(_dst4, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst5, _dst, 0); \ + __lsx_vst(_dst5, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst6, _dst, 0); \ + __lsx_vst(_dst6, _dst, 16); \ + _dst += _stride; \ + __lsx_vst(_dst7, _dst, 0); \ + __lsx_vst(_dst7, _dst, 16); \ + _dst += _stride; \ +} + +void ff_vert_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *left, + const uint8_t *src) +{ + __m128i src0; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + src0 = __lsx_vld(src, 0); + LSX_ST_8(src0, src0, src0, src0, src0, src0, src0, src0, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(src0, src0, src0, src0, src0, src0, src0, src0, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_vert_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *left, + const uint8_t *src) +{ + uint32_t row; + __m128i src0, src1; + + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src1); + for (row = 32; row--;) { + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst, 16); + dst += dst_stride; + } +} + +void ff_hor_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, + const uint8_t *top) +{ + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + src15 = __lsx_vldrepl_b(src, 0); + src14 = __lsx_vldrepl_b(src, 1); + src13 = __lsx_vldrepl_b(src, 2); + src12 = __lsx_vldrepl_b(src, 3); + src11 = __lsx_vldrepl_b(src, 4); + src10 = __lsx_vldrepl_b(src, 5); + src9 = __lsx_vldrepl_b(src, 6); + src8 = __lsx_vldrepl_b(src, 7); + src7 = __lsx_vldrepl_b(src, 8); + src6 = __lsx_vldrepl_b(src, 9); + src5 = __lsx_vldrepl_b(src, 10); + src4 = __lsx_vldrepl_b(src, 11); + src3 = __lsx_vldrepl_b(src, 12); + src2 = __lsx_vldrepl_b(src, 13); + src1 = __lsx_vldrepl_b(src, 14); + src0 = __lsx_vldrepl_b(src, 15); + LSX_ST_8(src0, src1, src2, src3, src4, src5, src6, src7, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(src8, src9, src10, src11, src12, src13, src14, src15, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_hor_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, + const uint8_t *top) +{ + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + __m128i src16, src17, src18, src19, src20, src21, src22, src23; + __m128i src24, src25, src26, src27, src28, src29, src30, src31; + + src31 = __lsx_vldrepl_b(src, 0); + src30 = __lsx_vldrepl_b(src, 1); + src29 = __lsx_vldrepl_b(src, 2); + src28 = __lsx_vldrepl_b(src, 3); + src27 = __lsx_vldrepl_b(src, 4); + src26 = __lsx_vldrepl_b(src, 5); + src25 = __lsx_vldrepl_b(src, 6); + src24 = __lsx_vldrepl_b(src, 7); + src23 = __lsx_vldrepl_b(src, 8); + src22 = __lsx_vldrepl_b(src, 9); + src21 = __lsx_vldrepl_b(src, 10); + src20 = __lsx_vldrepl_b(src, 11); + src19 = __lsx_vldrepl_b(src, 12); + src18 = __lsx_vldrepl_b(src, 13); + src17 = __lsx_vldrepl_b(src, 14); + src16 = __lsx_vldrepl_b(src, 15); + src15 = __lsx_vldrepl_b(src, 16); + src14 = __lsx_vldrepl_b(src, 17); + src13 = __lsx_vldrepl_b(src, 18); + src12 = __lsx_vldrepl_b(src, 19); + src11 = __lsx_vldrepl_b(src, 20); + src10 = __lsx_vldrepl_b(src, 21); + src9 = __lsx_vldrepl_b(src, 22); + src8 = __lsx_vldrepl_b(src, 23); + src7 = __lsx_vldrepl_b(src, 24); + src6 = __lsx_vldrepl_b(src, 25); + src5 = __lsx_vldrepl_b(src, 26); + src4 = __lsx_vldrepl_b(src, 27); + src3 = __lsx_vldrepl_b(src, 28); + src2 = __lsx_vldrepl_b(src, 29); + src1 = __lsx_vldrepl_b(src, 30); + src0 = __lsx_vldrepl_b(src, 31); + LSX_ST_8X16(src0, src1, src2, src3, src4, src5, src6, src7, + dst, dst_stride); + LSX_ST_8X16(src8, src9, src10, src11, src12, src13, src14, src15, + dst, dst_stride); + LSX_ST_8X16(src16, src17, src18, src19, src20, src21, src22, src23, + dst, dst_stride); + LSX_ST_8X16(src24, src25, src26, src27, src28, src29, src30, src31, + dst, dst_stride); +} + +void ff_dc_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src_left, + const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + + tmp0 = __lsx_vldrepl_w(src_top, 0); + tmp1 = __lsx_vldrepl_w(src_left, 0); + dst0 = __lsx_vilvl_w(tmp1, tmp0); + dst0 = __lsx_vhaddw_hu_bu(dst0, dst0); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 3); + dst0 = __lsx_vshuf4i_b(dst0, 0); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 0); +} + +#define INTRA_DC_TL_4X4(dir) \ +void ff_dc_##dir##_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + \ + tmp0 = __lsx_vldrepl_w(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 2); \ + dst0 = __lsx_vshuf4i_b(dst0, 0); \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_w(dst0, dst, 0, 0); \ +} +INTRA_DC_TL_4X4(top); +INTRA_DC_TL_4X4(left); + +void ff_dc_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src_left, + const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + + tmp0 = __lsx_vldrepl_d(src_top, 0); + tmp1 = __lsx_vldrepl_d(src_left, 0); + dst0 = __lsx_vilvl_d(tmp1, tmp0); + dst0 = __lsx_vhaddw_hu_bu(dst0, dst0); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 4); + dst0 = __lsx_vreplvei_b(dst0, 0); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 0); +} + +#define INTRA_DC_TL_8X8(dir) \ +void ff_dc_##dir##_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + \ + tmp0 = __lsx_vldrepl_d(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 3); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ + dst += dst_stride; \ + __lsx_vstelm_d(dst0, dst, 0, 0); \ +} + +INTRA_DC_TL_8X8(top); +INTRA_DC_TL_8X8(left); + +void ff_dc_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top) +{ + __m128i tmp0, tmp1, dst0; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + tmp0 = __lsx_vld(src_top, 0); + tmp1 = __lsx_vld(src_left, 0); + DUP2_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp0, tmp1); + dst0 = __lsx_vadd_h(tmp0, tmp1); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 5); + dst0 = __lsx_vreplvei_b(dst0, 0); + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, + dst_stride, stride2, stride3, stride4); +} + +#define INTRA_DC_TL_16X16(dir) \ +void ff_dc_##dir##_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, dst0; \ + ptrdiff_t stride2 = dst_stride << 1; \ + ptrdiff_t stride3 = stride2 + dst_stride; \ + ptrdiff_t stride4 = stride2 << 1; \ + \ + tmp0 = __lsx_vld(dir, 0); \ + dst0 = __lsx_vhaddw_hu_bu(tmp0, tmp0); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 4); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, \ + dst_stride, stride2, stride3, stride4); \ + dst += stride4; \ + LSX_ST_8(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst, \ + dst_stride, stride2, stride3, stride4); \ +} + +INTRA_DC_TL_16X16(top); +INTRA_DC_TL_16X16(left); + +void ff_dc_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top) +{ + __m128i tmp0, tmp1, tmp2, tmp3, dst0; + + DUP2_ARG2(__lsx_vld, src_top, 0, src_top, 16, tmp0, tmp1); + DUP2_ARG2(__lsx_vld, src_left, 0, src_left, 16, tmp2, tmp3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp2, tmp2, + tmp3, tmp3, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vadd_h, tmp0, tmp1, tmp2, tmp3, tmp0, tmp1); + dst0 = __lsx_vadd_h(tmp0, tmp1); + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); + dst0 = __lsx_vsrari_w(dst0, 6); + dst0 = __lsx_vreplvei_b(dst0, 0); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, + dst, dst_stride); +} + +#define INTRA_DC_TL_32X32(dir) \ +void ff_dc_##dir##_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, \ + const uint8_t *top) \ +{ \ + __m128i tmp0, tmp1, dst0; \ + \ + DUP2_ARG2(__lsx_vld, dir, 0, dir, 16, tmp0, tmp1); \ + DUP2_ARG2(__lsx_vhaddw_hu_bu, tmp0, tmp0, tmp1, tmp1, tmp0, tmp1); \ + dst0 = __lsx_vadd_h(tmp0, tmp1); \ + dst0 = __lsx_vhaddw_wu_hu(dst0, dst0); \ + dst0 = __lsx_vhaddw_du_wu(dst0, dst0); \ + dst0 = __lsx_vhaddw_qu_du(dst0, dst0); \ + dst0 = __lsx_vsrari_w(dst0, 5); \ + dst0 = __lsx_vreplvei_b(dst0, 0); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ + LSX_ST_8X16(dst0, dst0, dst0, dst0, dst0, dst0, dst0, dst0, \ + dst, dst_stride); \ +} + +INTRA_DC_TL_32X32(top); +INTRA_DC_TL_32X32(left); + +#define INTRA_PREDICT_VALDC_16X16_LSX(val) \ +void ff_dc_##val##_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, const uint8_t *top) \ +{ \ + __m128i out = __lsx_vldi(val); \ + ptrdiff_t stride2 = dst_stride << 1; \ + ptrdiff_t stride3 = stride2 + dst_stride; \ + ptrdiff_t stride4 = stride2 << 1; \ + \ + LSX_ST_8(out, out, out, out, out, out, out, out, dst, \ + dst_stride, stride2, stride3, stride4); \ + dst += stride4; \ + LSX_ST_8(out, out, out, out, out, out, out, out, dst, \ + dst_stride, stride2, stride3, stride4); \ +} + +INTRA_PREDICT_VALDC_16X16_LSX(127); +INTRA_PREDICT_VALDC_16X16_LSX(128); +INTRA_PREDICT_VALDC_16X16_LSX(129); + +#define INTRA_PREDICT_VALDC_32X32_LSX(val) \ +void ff_dc_##val##_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, \ + const uint8_t *left, const uint8_t *top) \ +{ \ + __m128i out = __lsx_vldi(val); \ + \ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ + LSX_ST_8X16(out, out, out, out, out, out, out, out, dst, dst_stride);\ +} + +INTRA_PREDICT_VALDC_32X32_LSX(127); +INTRA_PREDICT_VALDC_32X32_LSX(128); +INTRA_PREDICT_VALDC_32X32_LSX(129); + +void ff_tm_4x4_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, reg0, reg1; + __m128i src0, src1, src2, src3; + __m128i dst0, dst1, dst2, dst3; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vilvl_b, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, reg1, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src0, src0, src1, src1, src2, src2, src3, + src3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vssub_hu, dst0, reg0, dst1, reg0, dst2, reg0, dst3, reg0, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vsat_hu, dst0, 7, dst1, 7, dst2, 7, dst3, 7, + dst0, dst1, dst2, dst3); + DUP2_ARG2(__lsx_vpickev_b, dst1, dst0, dst3, dst2, dst0, dst1); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 2); +} + +void ff_tm_8x8_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i reg0, reg1; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp7, tmp6, tmp5, tmp4); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 4, src_left, 5, src_left, 6, src_left, + 7, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vilvl_b, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, reg1, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvl_b, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, reg1, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src0, src0, src1, src1, src2, src2, src3, + src3, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vhaddw_hu_bu, src4, src4, src5, src5, src6, src6, src7, + src7, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpickev_b, src1, src0, src3, src2, src5, src4, src7, src6, + src0, src1, src2, src3); + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 1); +} + +void ff_tm_16x16_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i reg0, reg1; + ptrdiff_t stride2 = dst_stride << 1; + ptrdiff_t stride3 = stride2 + dst_stride; + ptrdiff_t stride4 = stride2 << 1; + + reg0 = __lsx_vreplgr2vr_h(top_left); + reg1 = __lsx_vld(src_top_ptr, 0); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, src_left, + 3, tmp15, tmp14, tmp13, tmp12); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 4, src_left, 5, src_left, 6, src_left, + 7, tmp11, tmp10, tmp9, tmp8); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 8, src_left, 9, src_left, 10, + src_left, 11, tmp7, tmp6, tmp5, tmp4); + DUP4_ARG2(__lsx_vldrepl_b, src_left, 12, src_left, 13, src_left, 14, + src_left, 15, tmp3, tmp2, tmp1, tmp0); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, tmp3, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp4, reg1, tmp5, reg1, tmp6, reg1, tmp7, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp8, reg1, tmp9, reg1, tmp10, reg1, tmp11, + reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp8, reg1, tmp9, reg1, tmp10, reg1, tmp11, + reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp8, tmp9, tmp10, tmp11); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp12, reg1, tmp13, reg1, tmp14, reg1, + tmp15, reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp12, reg1, tmp13, reg1, tmp14, reg1, + tmp15, reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, reg0, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, reg0, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, src3, + tmp12, tmp13, tmp14, tmp15); + LSX_ST_8(tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, dst, + dst_stride, stride2, stride3, stride4); + dst += stride4; + LSX_ST_8(tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15, dst, + dst_stride, stride2, stride3, stride4); +} + +void ff_tm_32x32_lsx(uint8_t *dst, ptrdiff_t dst_stride, + const uint8_t *src_left, const uint8_t *src_top_ptr) +{ + uint8_t top_left = src_top_ptr[-1]; + uint32_t loop_cnt; + __m128i tmp0, tmp1, tmp2, tmp3, reg0, reg1, reg2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + + reg0 = __lsx_vreplgr2vr_h(top_left); + DUP2_ARG2(__lsx_vld, src_top_ptr, 0, src_top_ptr, 16, reg1, reg2); + + src_left += 28; + for (loop_cnt = 8; loop_cnt--;) { + DUP4_ARG2(__lsx_vldrepl_b, src_left, 0, src_left, 1, src_left, 2, + src_left, 3, tmp3, tmp2, tmp1, tmp0); + src_left -= 4; + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, + tmp3, reg1, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg1, tmp1, reg1, tmp2, reg1, + tmp3, reg1, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vssub_hu, src0, reg0, src1, reg0, src2, reg0, src3, + reg0, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vssub_hu, src4, reg0, src5, reg0, src6, reg0, src7, + reg0, src4, src5, src6, src7); + DUP4_ARG2(__lsx_vaddwev_h_bu, tmp0, reg2, tmp1, reg2, tmp2, reg2, + tmp3, reg2, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vaddwod_h_bu, tmp0, reg2, tmp1, reg2, tmp2, reg2, + tmp3, reg2, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vssub_hu, dst0, reg0, dst1, reg0, dst2, reg0, dst3, + reg0, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vssub_hu, dst4, reg0, dst5, reg0, dst6, reg0, dst7, + reg0, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vsat_hu, src0, 7, src1, 7, src2, 7, src3, 7, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vsat_hu, src4, 7, src5, 7, src6, 7, src7, 7, + src4, src5, src6, src7); + DUP4_ARG2(__lsx_vsat_hu, dst0, 7, dst1, 7, dst2, 7, dst3, 7, + dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vsat_hu, dst4, 7, dst5, 7, dst6, 7, dst7, 7, + dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vpackev_b, src4, src0, src5, src1, src6, src2, src7, + src3, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vpackev_b, dst4, dst0, dst5, dst1, dst6, dst2, dst7, + dst3, dst0, dst1, dst2, dst3); + __lsx_vst(src0, dst, 0); + __lsx_vst(dst0, dst, 16); + dst += dst_stride; + __lsx_vst(src1, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + __lsx_vst(src2, dst, 0); + __lsx_vst(dst2, dst, 16); + dst += dst_stride; + __lsx_vst(src3, dst, 0); + __lsx_vst(dst3, dst, 16); + dst += dst_stride; + } +} diff --git a/libavcodec/loongarch/vp9_lpf_lsx.c b/libavcodec/loongarch/vp9_lpf_lsx.c new file mode 100644 index 0000000000..8e1915b888 --- /dev/null +++ b/libavcodec/loongarch/vp9_lpf_lsx.c @@ -0,0 +1,3141 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * Contributed by Jin Bo + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "libavutil/common.h" +#include "vp9dsp_loongarch.h" + +#define LSX_LD_8(_src, _stride, _stride2, _stride3, _stride4, _in0, _in1, _in2, \ + _in3, _in4, _in5, _in6, _in7) \ +{ \ + _in0 = __lsx_vld(_src, 0); \ + _in1 = __lsx_vldx(_src, _stride); \ + _in2 = __lsx_vldx(_src, _stride2); \ + _in3 = __lsx_vldx(_src, _stride3); \ + _src += _stride4; \ + _in4 = __lsx_vld(_src, 0); \ + _in5 = __lsx_vldx(_src, _stride); \ + _in6 = __lsx_vldx(_src, _stride2); \ + _in7 = __lsx_vldx(_src, _stride3); \ +} + +#define LSX_ST_8(_dst0, _dst1, _dst2, _dst3, _dst4, _dst5, _dst6, _dst7, \ + _dst, _stride, _stride2, _stride3, _stride4) \ +{ \ + __lsx_vst(_dst0, _dst, 0); \ + __lsx_vstx(_dst1, _dst, _stride); \ + __lsx_vstx(_dst2, _dst, _stride2); \ + __lsx_vstx(_dst3, _dst, _stride3); \ + _dst += _stride4; \ + __lsx_vst(_dst4, _dst, 0); \ + __lsx_vstx(_dst5, _dst, _stride); \ + __lsx_vstx(_dst6, _dst, _stride2); \ + __lsx_vstx(_dst7, _dst, _stride3); \ +} + +#define VP9_LPF_FILTER4_4W(p1_src, p0_src, q0_src, q1_src, mask_src, hev_src, \ + p1_dst, p0_dst, q0_dst, q1_dst) \ +{ \ + __m128i p1_tmp, p0_tmp, q0_tmp, q1_tmp, q0_sub_p0, filt, filt1, filt2; \ + const __m128i cnst3b = __lsx_vldi(3); \ + const __m128i cnst4b = __lsx_vldi(4); \ + \ + p1_tmp = __lsx_vxori_b(p1_src, 0x80); \ + p0_tmp = __lsx_vxori_b(p0_src, 0x80); \ + q0_tmp = __lsx_vxori_b(q0_src, 0x80); \ + q1_tmp = __lsx_vxori_b(q1_src, 0x80); \ + \ + filt = __lsx_vssub_b(p1_tmp, q1_tmp); \ + \ + filt = filt & hev_src; \ + \ + q0_sub_p0 = __lsx_vssub_b(q0_tmp, p0_tmp); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = __lsx_vsadd_b(filt, q0_sub_p0); \ + filt = filt & mask_src; \ + \ + filt1 = __lsx_vsadd_b(filt, cnst4b); \ + filt1 = __lsx_vsrai_b(filt1, 3); \ + \ + filt2 = __lsx_vsadd_b(filt, cnst3b); \ + filt2 = __lsx_vsrai_b(filt2, 3); \ + \ + q0_tmp = __lsx_vssub_b(q0_tmp, filt1); \ + q0_dst = __lsx_vxori_b(q0_tmp, 0x80); \ + p0_tmp = __lsx_vsadd_b(p0_tmp, filt2); \ + p0_dst = __lsx_vxori_b(p0_tmp, 0x80); \ + \ + filt = __lsx_vsrari_b(filt1, 1); \ + hev_src = __lsx_vxori_b(hev_src, 0xff); \ + filt = filt & hev_src; \ + \ + q1_tmp = __lsx_vssub_b(q1_tmp, filt); \ + q1_dst = __lsx_vxori_b(q1_tmp, 0x80); \ + p1_tmp = __lsx_vsadd_b(p1_tmp, filt); \ + p1_dst = __lsx_vxori_b(p1_tmp, 0x80); \ +} + +#define VP9_FLAT4(p3_src, p2_src, p0_src, q0_src, q2_src, q3_src, flat_dst) \ +{ \ + __m128i f_tmp = __lsx_vldi(1); \ + __m128i p2_a_sub_p0, q2_a_sub_q0, p3_a_sub_p0, q3_a_sub_q0; \ + \ + p2_a_sub_p0 = __lsx_vabsd_bu(p2_src, p0_src); \ + q2_a_sub_q0 = __lsx_vabsd_bu(q2_src, q0_src); \ + p3_a_sub_p0 = __lsx_vabsd_bu(p3_src, p0_src); \ + q3_a_sub_q0 = __lsx_vabsd_bu(q3_src, q0_src); \ + \ + p2_a_sub_p0 = __lsx_vmax_bu(p2_a_sub_p0, q2_a_sub_q0); \ + flat_dst = __lsx_vmax_bu(p2_a_sub_p0, flat_dst); \ + p3_a_sub_p0 = __lsx_vmax_bu(p3_a_sub_p0, q3_a_sub_q0); \ + flat_dst = __lsx_vmax_bu(p3_a_sub_p0, flat_dst); \ + \ + flat_dst = __lsx_vslt_bu(f_tmp, flat_dst); \ + flat_dst = __lsx_vxori_b(flat_dst, 0xff); \ + flat_dst = flat_dst & mask; \ +} + +#define VP9_FLAT5(p7_src, p6_src, p5_src, p4_src, p0_src, q0_src, q4_src, \ + q5_src, q6_src, q7_src, flat_src, flat2_dst) \ +{ \ + __m128i f_tmp = __lsx_vldi(1); \ + __m128i p4_a_sub_p0, q4_a_sub_q0, p5_a_sub_p0, q5_a_sub_q0; \ + __m128i p6_a_sub_p0, q6_a_sub_q0, p7_a_sub_p0, q7_a_sub_q0; \ + \ + p4_a_sub_p0 = __lsx_vabsd_bu(p4_src, p0_src); \ + q4_a_sub_q0 = __lsx_vabsd_bu(q4_src, q0_src); \ + p5_a_sub_p0 = __lsx_vabsd_bu(p5_src, p0_src); \ + q5_a_sub_q0 = __lsx_vabsd_bu(q5_src, q0_src); \ + p6_a_sub_p0 = __lsx_vabsd_bu(p6_src, p0_src); \ + q6_a_sub_q0 = __lsx_vabsd_bu(q6_src, q0_src); \ + p7_a_sub_p0 = __lsx_vabsd_bu(p7_src, p0_src); \ + q7_a_sub_q0 = __lsx_vabsd_bu(q7_src, q0_src); \ + \ + p4_a_sub_p0 = __lsx_vmax_bu(p4_a_sub_p0, q4_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p5_a_sub_p0, q5_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p4_a_sub_p0, flat2_dst); \ + p6_a_sub_p0 = __lsx_vmax_bu(p6_a_sub_p0, q6_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p6_a_sub_p0, flat2_dst); \ + p7_a_sub_p0 = __lsx_vmax_bu(p7_a_sub_p0, q7_a_sub_q0); \ + flat2_dst = __lsx_vmax_bu(p7_a_sub_p0, flat2_dst); \ + \ + flat2_dst = __lsx_vslt_bu(f_tmp, flat2_dst); \ + flat2_dst = __lsx_vxori_b(flat2_dst, 0xff); \ + flat2_dst = flat2_dst & flat_src; \ +} + +#define VP9_FILTER8(p3_src, p2_src, p1_src, p0_src, \ + q0_src, q1_src, q2_src, q3_src, \ + p2_filt8_dst, p1_filt8_dst, p0_filt8_dst, \ + q0_filt8_dst, q1_filt8_dst, q2_filt8_dst) \ +{ \ + __m128i tmp0, tmp1, tmp2; \ + \ + tmp2 = __lsx_vadd_h(p2_src, p1_src); \ + tmp2 = __lsx_vadd_h(tmp2, p0_src); \ + tmp0 = __lsx_vslli_h(p3_src, 1); \ + \ + tmp0 = __lsx_vadd_h(tmp0, tmp2); \ + tmp0 = __lsx_vadd_h(tmp0, q0_src); \ + tmp1 = __lsx_vadd_h(tmp0, p3_src); \ + tmp1 = __lsx_vadd_h(tmp1, p2_src); \ + p2_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vadd_h(tmp0, p1_src); \ + tmp1 = __lsx_vadd_h(tmp1, q1_src); \ + p1_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vadd_h(q2_src, q1_src); \ + tmp1 = __lsx_vadd_h(tmp1, q0_src); \ + tmp2 = __lsx_vadd_h(tmp2, tmp1); \ + tmp0 = __lsx_vadd_h(tmp2, p0_src); \ + tmp0 = __lsx_vadd_h(tmp0, p3_src); \ + p0_filt8_dst = __lsx_vsrari_h(tmp0, 3); \ + \ + tmp0 = __lsx_vadd_h(q2_src, q3_src); \ + tmp0 = __lsx_vadd_h(tmp0, p0_src); \ + tmp0 = __lsx_vadd_h(tmp0, tmp1); \ + tmp1 = __lsx_vadd_h(q3_src, q3_src); \ + tmp1 = __lsx_vadd_h(tmp1, tmp0); \ + q2_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp0 = __lsx_vadd_h(tmp2, q3_src); \ + tmp1 = __lsx_vadd_h(tmp0, q0_src); \ + q0_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ + \ + tmp1 = __lsx_vsub_h(tmp0, p2_src); \ + tmp0 = __lsx_vadd_h(q1_src, q3_src); \ + tmp1 = __lsx_vadd_h(tmp0, tmp1); \ + q1_filt8_dst = __lsx_vsrari_h(tmp1, 3); \ +} + +#define LPF_MASK_HEV(p3_src, p2_src, p1_src, p0_src, q0_src, q1_src, \ + q2_src, q3_src, limit_src, b_limit_src, thresh_src, \ + hev_dst, mask_dst, flat_dst) \ +{ \ + __m128i p3_asub_p2_tmp, p2_asub_p1_tmp, p1_asub_p0_tmp, q1_asub_q0_tmp; \ + __m128i p1_asub_q1_tmp, p0_asub_q0_tmp, q3_asub_q2_tmp, q2_asub_q1_tmp; \ + \ + /* absolute subtraction of pixel values */ \ + p3_asub_p2_tmp = __lsx_vabsd_bu(p3_src, p2_src); \ + p2_asub_p1_tmp = __lsx_vabsd_bu(p2_src, p1_src); \ + p1_asub_p0_tmp = __lsx_vabsd_bu(p1_src, p0_src); \ + q1_asub_q0_tmp = __lsx_vabsd_bu(q1_src, q0_src); \ + q2_asub_q1_tmp = __lsx_vabsd_bu(q2_src, q1_src); \ + q3_asub_q2_tmp = __lsx_vabsd_bu(q3_src, q2_src); \ + p0_asub_q0_tmp = __lsx_vabsd_bu(p0_src, q0_src); \ + p1_asub_q1_tmp = __lsx_vabsd_bu(p1_src, q1_src); \ + \ + /* calculation of hev */ \ + flat_dst = __lsx_vmax_bu(p1_asub_p0_tmp, q1_asub_q0_tmp); \ + hev_dst = __lsx_vslt_bu(thresh_src, flat_dst); \ + \ + /* calculation of mask */ \ + p0_asub_q0_tmp = __lsx_vsadd_bu(p0_asub_q0_tmp, p0_asub_q0_tmp); \ + p1_asub_q1_tmp = __lsx_vsrli_b(p1_asub_q1_tmp, 1); \ + p0_asub_q0_tmp = __lsx_vsadd_bu(p0_asub_q0_tmp, p1_asub_q1_tmp); \ + \ + mask_dst = __lsx_vslt_bu(b_limit_src, p0_asub_q0_tmp); \ + mask_dst = __lsx_vmax_bu(flat_dst, mask_dst); \ + p3_asub_p2_tmp = __lsx_vmax_bu(p3_asub_p2_tmp, p2_asub_p1_tmp); \ + mask_dst = __lsx_vmax_bu(p3_asub_p2_tmp, mask_dst); \ + q2_asub_q1_tmp = __lsx_vmax_bu(q2_asub_q1_tmp, q3_asub_q2_tmp); \ + mask_dst = __lsx_vmax_bu(q2_asub_q1_tmp, mask_dst); \ + \ + mask_dst = __lsx_vslt_bu(limit_src, mask_dst); \ + mask_dst = __lsx_vxori_b(mask_dst, 0xff); \ +} + +void ff_loop_filter_v_4_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0, p1_out, p0_out, q0_out, q1_out; + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); +} + +void ff_loop_filter_v_44_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh0, b_limit0; + __m128i limit0, thresh1, b_limit1, limit1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh0 = __lsx_vreplgr2vr_b(thresh_ptr); + thresh1 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh0 = __lsx_vilvl_d(thresh1, thresh0); + + b_limit0 = __lsx_vreplgr2vr_b(b_limit_ptr); + b_limit1 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit0 = __lsx_vilvl_d(b_limit1, b_limit0); + + limit0 = __lsx_vreplgr2vr_b(limit_ptr); + limit1 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit0 = __lsx_vilvl_d(limit1, limit0); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + + __lsx_vst(p1, dst - stride2, 0); + __lsx_vst(p0, dst - stride, 0); + __lsx_vst(q0, dst , 0); + __lsx_vst(q1, dst + stride, 0); +} + +void ff_loop_filter_v_8_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i p2_filter8, p1_filter8, p0_filter8; + __m128i q0_filter8, q1_filter8, q2_filter8; + __m128i p3_l, p2_l, p1_l, p0_l, q3_l, q2_l, q1_l, q0_l; + __m128i zero = __lsx_vldi(0); + + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filter8, + p1_filter8, p0_filter8, q0_filter8, q1_filter8, q2_filter8); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, zero, p2_filter8, zero, p1_filter8, + zero, p0_filter8, zero, q0_filter8, p2_filter8, + p1_filter8, p0_filter8, q0_filter8); + DUP2_ARG2(__lsx_vpickev_b, zero, q1_filter8, zero, q2_filter8, + q1_filter8, q2_filter8); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filter8, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filter8, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filter8, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filter8, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filter8, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filter8, flat); + + __lsx_vstelm_d(p2_out, dst - stride3, 0, 0); + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst, 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + __lsx_vstelm_d(q2_out, dst + stride2, 0, 0); + } +} + +void ff_loop_filter_v_88_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vst(p1_out, dst - stride2, 0); + __lsx_vst(p0_out, dst - stride, 0); + __lsx_vst(q0_out, dst, 0); + __lsx_vst(q1_out, dst + stride, 0); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +void ff_loop_filter_v_84_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, + p1_filt8_l, p0_filt8_l, p0_filt8_l, q0_filt8_l, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +void ff_loop_filter_v_48_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, tmp, thresh, b_limit, limit; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = { 0 }; + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + tmp = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(tmp, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + tmp = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(tmp, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + tmp = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(tmp, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvh_d(flat, zero); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + } else { + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_h, p1_filt8_h, + p1_filt8_h, p0_filt8_h, p0_filt8_h, q0_filt8_h, q0_filt8_h, + p2_filt8_h, p1_filt8_h, p0_filt8_h, q0_filt8_h); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_h, q2_filt8_h, + q2_filt8_h, q1_filt8_h, q2_filt8_h); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_h, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_h, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_h, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_h, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_h, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_h, flat); + + __lsx_vstx(p2_out, dst, -stride3); + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + __lsx_vstx(q2_out, dst, stride2); + } +} + +static int32_t vp9_hz_lpf_t4_and_t8_16w(uint8_t *dst, ptrdiff_t stride, + uint8_t *filter48, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstx(p1_out, dst, -stride2); + __lsx_vstx(p0_out, dst, -stride); + __lsx_vst(q0_out, dst, 0); + __lsx_vstx(q1_out, dst, stride); + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static void vp9_hz_lpf_t16_16w(uint8_t *dst, ptrdiff_t stride, + uint8_t *filter48) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - stride4; + uint8_t *dst_tmp1 = dst + stride4; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + __m128i flat, flat2, filter8; + __m128i zero = __lsx_vldi(0); + __m128i out_h, out_l; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 p7_h_in, p6_h_in, p5_h_in, p4_h_in; + v8u16 p3_h_in, p2_h_in, p1_h_in, p0_h_in; + v8u16 q7_h_in, q6_h_in, q5_h_in, q4_h_in; + v8u16 q3_h_in, q2_h_in, q1_h_in, q0_h_in; + v8u16 tmp0_l, tmp1_l, tmp0_h, tmp1_h; + + flat = __lsx_vld(filter48, 96); + + DUP4_ARG2(__lsx_vldx, dst_tmp, -stride4, dst_tmp, -stride3, dst_tmp, + -stride2, dst_tmp, -stride, p7, p6, p5, p4); + p3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp, stride3); + + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + q4 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, stride, dst_tmp1, stride2, q5, q6); + q7 = __lsx_vldx(dst_tmp1, stride3); + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, filter48, + 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + __lsx_vstx(p2, dst, -stride3); + __lsx_vstx(p1, dst, -stride2); + __lsx_vstx(p0, dst, -stride); + __lsx_vst(q0, dst, 0); + __lsx_vstx(q1, dst, stride); + __lsx_vstx(q2, dst, stride2); + } else { + dst = dst_tmp - stride3; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + p7_h_in = (v8u16)__lsx_vilvh_b(zero, p7); + p6_h_in = (v8u16)__lsx_vilvh_b(zero, p6); + p5_h_in = (v8u16)__lsx_vilvh_b(zero, p5); + p4_h_in = (v8u16)__lsx_vilvh_b(zero, p4); + + p3_h_in = (v8u16)__lsx_vilvh_b(zero, p3); + p2_h_in = (v8u16)__lsx_vilvh_b(zero, p2); + p1_h_in = (v8u16)__lsx_vilvh_b(zero, p1); + p0_h_in = (v8u16)__lsx_vilvh_b(zero, p0); + q0_h_in = (v8u16)__lsx_vilvh_b(zero, q0); + + tmp0_h = p7_h_in << 3; + tmp0_h -= p7_h_in; + tmp0_h += p6_h_in; + tmp0_h += q0_h_in; + tmp1_h = p6_h_in + p5_h_in; + tmp1_h += p4_h_in; + tmp1_h += p3_h_in; + tmp1_h += p2_h_in; + tmp1_h += p1_h_in; + tmp1_h += p0_h_in; + tmp1_h += tmp0_h; + + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vst(p6, dst, 0); + dst += stride; + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q1_h_in = (v8u16)__lsx_vilvh_b(zero, q1); + tmp0_h = p5_h_in - p6_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vst(p5, dst, 0); + dst += stride; + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q2_h_in = (v8u16)__lsx_vilvh_b(zero, q2); + tmp0_h = p4_h_in - p5_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vst(p4, dst, 0); + dst += stride; + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q3_h_in = (v8u16)__lsx_vilvh_b(zero, q3); + tmp0_h = p3_h_in - p4_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vst(p3, dst, 0); + dst += stride; + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q4_h_in = (v8u16)__lsx_vilvh_b(zero, q4); + tmp0_h = p2_h_in - p3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q5_h_in = (v8u16)__lsx_vilvh_b(zero, q5); + tmp0_h = p1_h_in - p2_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q6_h_in = (v8u16)__lsx_vilvh_b(zero, q6); + tmp0_h = p0_h_in - p1_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + q7_h_in = (v8u16)__lsx_vilvh_b(zero, q7); + tmp0_h = q7_h_in - p0_h_in; + tmp0_h += q0_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q0_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p6_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q1_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p5_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 0); + dst += stride; + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q2_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p4_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vst(q3, dst, 0); + dst += stride; + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p3_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vst(q4, dst, 0); + dst += stride; + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q4_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p2_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vst(q5, dst, 0); + dst += stride; + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + tmp0_h = q7_h_in - q5_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p1_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vst(q6, dst, 0); + } +} + +void ff_loop_filter_v_16_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t filter48[16 * 8] __attribute__ ((aligned(16))); + uint8_t early_exit = 0; + + early_exit = vp9_hz_lpf_t4_and_t8_16w(dst, stride, &filter48[0], + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + vp9_hz_lpf_t16_16w(dst, stride, filter48); + } +} + +void ff_loop_filter_v_16_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - stride4; + uint8_t *dst_tmp1 = dst + stride4; + __m128i zero = __lsx_vldi(0); + __m128i flat2, mask, hev, flat, thresh, b_limit, limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0, p7, p6, p5, p4, q4, q5, q6, q7; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i p0_filter16, p1_filter16; + __m128i p2_filter8, p1_filter8, p0_filter8; + __m128i q0_filter8, q1_filter8, q2_filter8; + __m128i p7_l, p6_l, p5_l, p4_l, q7_l, q6_l, q5_l, q4_l; + __m128i p3_l, p2_l, p1_l, p0_l, q3_l, q2_l, q1_l, q0_l; + __m128i tmp0, tmp1, tmp2; + + /* load vector elements */ + DUP4_ARG2(__lsx_vldx, dst, -stride4, dst, -stride3, dst, -stride2, + dst, -stride, p3, p2, p1, p0); + q0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, stride, dst, stride2, q1, q2); + q3 = __lsx_vldx(dst, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + __lsx_vstelm_d(p1_out, dst - stride2, 0, 0); + __lsx_vstelm_d(p0_out, dst - stride, 0, 0); + __lsx_vstelm_d(q0_out, dst , 0, 0); + __lsx_vstelm_d(q1_out, dst + stride, 0, 0); + } else { + /* convert 8 bit input data into 16 bit */ + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, + p2_filter8, p1_filter8, p0_filter8, q0_filter8, + q1_filter8, q2_filter8); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, zero, p2_filter8, zero, p1_filter8, + zero, p0_filter8, zero, q0_filter8, p2_filter8, + p1_filter8, p0_filter8, q0_filter8); + DUP2_ARG2(__lsx_vpickev_b, zero, q1_filter8, zero, q2_filter8, + q1_filter8, q2_filter8); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filter8, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filter8, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filter8, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filter8, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filter8, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filter8, flat); + + /* load 16 vector elements */ + DUP4_ARG2(__lsx_vld, dst_tmp - stride4, 0, dst_tmp - stride3, 0, + dst_tmp - stride2, 0, dst_tmp - stride, 0, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp1, 0, dst_tmp1 + stride, 0, + dst_tmp1 + stride2, 0, dst_tmp1 + stride3, 0, q4, q5, q6, q7); + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + dst -= stride3; + __lsx_vstelm_d(p2_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p0_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q0_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q1_out, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(q2_out, dst, 0, 0); + } else { + /* LSB(right) 8 pixel operation */ + DUP4_ARG2(__lsx_vilvl_b, zero, p7, zero, p6, zero, p5, zero, p4, + p7_l, p6_l, p5_l, p4_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q4, zero, q5, zero, q6, zero, q7, + q4_l, q5_l, q6_l, q7_l); + + tmp0 = __lsx_vslli_h(p7_l, 3); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp0 = __lsx_vadd_h(tmp0, p6_l); + tmp0 = __lsx_vadd_h(tmp0, q0_l); + + dst = dst_tmp - stride3; + + /* calculation of p6 and p5 */ + tmp1 = __lsx_vadd_h(p6_l, p5_l); + tmp1 = __lsx_vadd_h(tmp1, p4_l); + tmp1 = __lsx_vadd_h(tmp1, p3_l); + tmp1 = __lsx_vadd_h(tmp1, p2_l); + tmp1 = __lsx_vadd_h(tmp1, p1_l); + tmp1 = __lsx_vadd_h(tmp1, p0_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp0 = __lsx_vsub_h(p5_l, p6_l); + tmp0 = __lsx_vadd_h(tmp0, q1_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p6, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p5, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p4 and p3 */ + tmp0 = __lsx_vsub_h(p4_l, p5_l); + tmp0 = __lsx_vadd_h(tmp0, q2_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(p3_l, p4_l); + tmp2 = __lsx_vadd_h(tmp2, q3_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p4, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p3, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p2 and p1 */ + tmp0 = __lsx_vsub_h(p2_l, p3_l); + tmp0 = __lsx_vadd_h(tmp0, q4_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(p1_l, p2_l); + tmp2 = __lsx_vadd_h(tmp2, q5_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p2_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(p1_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of p0 and q0 */ + tmp0 = __lsx_vsub_h(p0_l, p1_l); + tmp0 = __lsx_vadd_h(tmp0, q6_l); + tmp0 = __lsx_vsub_h(tmp0, p7_l); + tmp2 = __lsx_vsub_h(q7_l, p0_l); + tmp2 = __lsx_vadd_h(tmp2, q0_l); + tmp2 = __lsx_vsub_h(tmp2, p7_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h((__m128i)tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h((__m128i)tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(p0_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q0_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q1 and q2 */ + tmp0 = __lsx_vsub_h(q7_l, q0_l); + tmp0 = __lsx_vadd_h(tmp0, q1_l); + tmp0 = __lsx_vsub_h(tmp0, p6_l); + tmp2 = __lsx_vsub_h(q7_l, q1_l); + tmp2 = __lsx_vadd_h(tmp2, q2_l); + tmp2 = __lsx_vsub_h(tmp2, p5_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q1_out, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q2_out, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q3 and q4 */ + tmp0 = __lsx_vsub_h(q7_l, q2_l); + tmp0 = __lsx_vadd_h(tmp0, q3_l); + tmp0 = __lsx_vsub_h(tmp0, p4_l); + tmp2 = __lsx_vsub_h(q7_l, q3_l); + tmp2 = __lsx_vadd_h(tmp2, q4_l); + tmp2 = __lsx_vsub_h(tmp2, p3_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q3, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q4, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + dst += stride; + + /* calculation of q5 and q6 */ + tmp0 = __lsx_vsub_h(q7_l, q4_l); + tmp0 = __lsx_vadd_h(tmp0, q5_l); + tmp0 = __lsx_vsub_h(tmp0, p2_l); + tmp2 = __lsx_vsub_h(q7_l, q5_l); + tmp2 = __lsx_vadd_h(tmp2, q6_l); + tmp2 = __lsx_vsub_h(tmp2, p1_l); + tmp1 = __lsx_vadd_h(tmp1, tmp0); + p0_filter16 = __lsx_vsrari_h(tmp1, 4); + tmp1 = __lsx_vadd_h(tmp1, tmp2); + p1_filter16 = __lsx_vsrari_h(tmp1, 4); + DUP2_ARG2(__lsx_vpickev_b, zero, p0_filter16, zero, + p1_filter16, p0_filter16, p1_filter16); + p0_filter16 = __lsx_vbitsel_v(q5, p0_filter16, flat2); + p1_filter16 = __lsx_vbitsel_v(q6, p1_filter16, flat2); + __lsx_vstelm_d(p0_filter16, dst, 0, 0); + dst += stride; + __lsx_vstelm_d(p1_filter16, dst, 0, 0); + } + } +} + +void ff_loop_filter_h_4_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp1 = dst - 4; + uint8_t *dst_tmp2 = dst_tmp1 + stride4; + __m128i mask, hev, flat, limit, thresh, b_limit; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i vec0, vec1, vec2, vec3; + + p3 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, stride, dst_tmp1, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp1, stride3); + q0 = __lsx_vld(dst_tmp2, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp2, stride, dst_tmp2, stride2, q1, q2); + q3 = __lsx_vldx(dst_tmp2, stride3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + LSX_TRANSPOSE8x8_B(p3, p2, p1, p0, q0, q1, q2, q3, + p3, p2, p1, p0, q0, q1, q2, q3); + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); +} + +void ff_loop_filter_h_44_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i mask, hev, flat; + __m128i thresh0, b_limit0, limit0, thresh1, b_limit1, limit1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i row8, row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + row0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row1, row2); + row3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row8 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row9, row10); + row11 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh0 = __lsx_vreplgr2vr_b(thresh_ptr); + thresh1 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh0 = __lsx_vilvl_d(thresh1, thresh0); + + b_limit0 = __lsx_vreplgr2vr_b(b_limit_ptr); + b_limit1 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit0 = __lsx_vilvl_d(b_limit1, b_limit0); + + limit0 = __lsx_vreplgr2vr_b(limit_ptr); + limit1 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit0 = __lsx_vilvl_d(limit1, limit0); + + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit0, b_limit0, thresh0, + hev, mask, flat); + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1, p0, q0, q1); + DUP2_ARG2(__lsx_vilvl_b, p0, p1, q1, q0, tmp0, tmp1); + tmp2 = __lsx_vilvl_h(tmp1, tmp0); + tmp3 = __lsx_vilvh_h(tmp1, tmp0); + DUP2_ARG2(__lsx_vilvh_b, p0, p1, q1, q0, tmp0, tmp1); + tmp4 = __lsx_vilvl_h(tmp1, tmp0); + tmp5 = __lsx_vilvh_h(tmp1, tmp0); + + dst -= 2; + __lsx_vstelm_w(tmp2, dst, 0, 0); + __lsx_vstelm_w(tmp2, dst + stride, 0, 1); + __lsx_vstelm_w(tmp2, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp3, dst, 0, 0); + __lsx_vstelm_w(tmp3, dst + stride, 0, 1); + __lsx_vstelm_w(tmp3, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp4, dst, 0, 0); + __lsx_vstelm_w(tmp4, dst + stride, 0, 1); + __lsx_vstelm_w(tmp4, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(tmp5, dst, 0, 0); + __lsx_vstelm_w(tmp5, dst + stride, 0, 1); + __lsx_vstelm_w(tmp5, dst + stride2, 0, 2); + __lsx_vstelm_w(tmp5, dst + stride3, 0, 3); +} + +void ff_loop_filter_h_8_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3, vec4; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + p3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p2, p1); + p0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q1, q2); + q3 = __lsx_vldx(dst_tmp, stride3); + + LSX_TRANSPOSE8x8_B(p3, p2, p1, p0, q0, q1, q2, q3, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + /* Store 4 pixels p1-_q1 */ + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, + p1_filt8_l, p0_filt8_l, p0_filt8_l, q0_filt8_l, + q0_filt8_l, p2_filt8_l, p1_filt8_l, p0_filt8_l, + q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + /* Store 6 pixels p2-_q2 */ + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + vec4 = __lsx_vilvl_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_h(vec4, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 1); + __lsx_vstelm_h(vec4, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 2); + __lsx_vstelm_h(vec4, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec2, dst, 0, 3); + __lsx_vstelm_h(vec4, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec4, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec4, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec4, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec4, dst, 4, 7); + } +} + +void ff_loop_filter_h_88_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + + /* filter8 */ + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, q0_filt8_l, + p2_filt8_l, p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +void ff_loop_filter_h_84_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_l, p2_filt8_l, p1_filt8_l, p1_filt8_l, + p0_filt8_l, p0_filt8_l, q0_filt8_l, q0_filt8_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_l, q1_filt8_l, q2_filt8_l, q2_filt8_l, + q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +void ff_loop_filter_h_48_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + uint8_t *dst_tmp = dst - 4; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p1_out, p0_out, q0_out, q1_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i row4, row5, row6, row7, row12, row13, row14, row15; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + __m128i zero = __lsx_vldi(0); + + p0 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, p1, p2); + p3 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row4 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row5, row6); + row7 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + q3 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, q2, q1); + q0 = __lsx_vldx(dst_tmp, stride3); + dst_tmp += stride4; + row12 = __lsx_vld(dst_tmp, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp, stride, dst_tmp, stride2, row13, row14); + row15 = __lsx_vldx(dst_tmp, stride3); + + /* transpose 16x8 matrix into 8x16 */ + LSX_TRANSPOSE16x8_B(p0, p1, p2, p3, row4, row5, row6, row7, + q3, q2, q1, q0, row12, row13, row14, row15, + p3, p2, p1, p0, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + vec0 = __lsx_vreplgr2vr_b(thresh_ptr >> 8); + thresh = __lsx_vilvl_d(vec0, thresh); + + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + vec0 = __lsx_vreplgr2vr_b(b_limit_ptr >> 8); + b_limit = __lsx_vilvl_d(vec0, b_limit); + + limit = __lsx_vreplgr2vr_b(limit_ptr); + vec0 = __lsx_vreplgr2vr_b(limit_ptr >> 8); + limit = __lsx_vilvl_d(vec0, limit); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvh_d(flat, zero); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst -= 2; + __lsx_vstelm_w(vec2, dst, 0, 0); + __lsx_vstelm_w(vec2, dst + stride, 0, 1); + __lsx_vstelm_w(vec2, dst + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_w(vec3, dst + stride, 0, 1); + __lsx_vstelm_w(vec3, dst + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_w(vec4, dst + stride, 0, 1); + __lsx_vstelm_w(vec4, dst + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst + stride3, 0, 3); + dst += stride4; + __lsx_vstelm_w(vec5, dst, 0, 0); + __lsx_vstelm_w(vec5, dst + stride, 0, 1); + __lsx_vstelm_w(vec5, dst + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst + stride3, 0, 3); + } else { + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_h, p1_filt8_h, + p1_filt8_h, p0_filt8_h, p0_filt8_h, q0_filt8_h, q0_filt8_h, + p2_filt8_h, p1_filt8_h, p0_filt8_h, q0_filt8_h); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_h, q2_filt8_h, + q2_filt8_h, q1_filt8_h, q2_filt8_h); + + /* store pixel values */ + p2 = __lsx_vbitsel_v(p2, p2_filt8_h, flat); + p1 = __lsx_vbitsel_v(p1_out, p1_filt8_h, flat); + p0 = __lsx_vbitsel_v(p0_out, p0_filt8_h, flat); + q0 = __lsx_vbitsel_v(q0_out, q0_filt8_h, flat); + q1 = __lsx_vbitsel_v(q1_out, q1_filt8_h, flat); + q2 = __lsx_vbitsel_v(q2, q2_filt8_h, flat); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst -= 3; + __lsx_vstelm_w(vec3, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec3, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 0); + __lsx_vstelm_h(vec2, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 1); + __lsx_vstelm_h(vec2, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 2); + __lsx_vstelm_h(vec2, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec4, dst, 0, 3); + __lsx_vstelm_h(vec2, dst, 4, 7); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 0); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 1); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 2); + dst += stride; + __lsx_vstelm_w(vec6, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 3); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 0); + __lsx_vstelm_h(vec5, dst, 4, 4); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 1); + __lsx_vstelm_h(vec5, dst, 4, 5); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 2); + __lsx_vstelm_h(vec5, dst, 4, 6); + dst += stride; + __lsx_vstelm_w(vec7, dst, 0, 3); + __lsx_vstelm_h(vec5, dst, 4, 7); + } +} + +static void vp9_transpose_16x8_to_8x16(uint8_t *input, ptrdiff_t in_pitch, + uint8_t *output) +{ + __m128i p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + ptrdiff_t in_pitch2 = in_pitch << 1; + ptrdiff_t in_pitch3 = in_pitch2 + in_pitch; + ptrdiff_t in_pitch4 = in_pitch2 << 1; + + LSX_LD_8(input, in_pitch, in_pitch2, in_pitch3, in_pitch4, + p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, p0_org); + /* 8x8 transpose */ + LSX_TRANSPOSE8x8_B(p7_org, p6_org, p5_org, p4_org, p3_org, p2_org, p1_org, + p0_org, p7, p6, p5, p4, p3, p2, p1, p0); + /* 8x8 transpose */ + DUP4_ARG2(__lsx_vilvh_b, p5_org, p7_org, p4_org, p6_org, p1_org, + p3_org, p0_org, p2_org, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, tmp1, tmp0, tmp3, tmp2, tmp4, tmp6); + DUP2_ARG2(__lsx_vilvh_b, tmp1, tmp0, tmp3, tmp2, tmp5, tmp7); + DUP2_ARG2(__lsx_vilvl_w, tmp6, tmp4, tmp7, tmp5, q0, q4); + DUP2_ARG2(__lsx_vilvh_w, tmp6, tmp4, tmp7, tmp5, q2, q6); + DUP4_ARG2(__lsx_vbsrl_v, q0, 8, q2, 8, q4, 8, q6, 8, q1, q3, q5, q7); + + __lsx_vst(p7, output, 0); + __lsx_vst(p6, output, 16); + __lsx_vst(p5, output, 32); + __lsx_vst(p4, output, 48); + __lsx_vst(p3, output, 64); + __lsx_vst(p2, output, 80); + __lsx_vst(p1, output, 96); + __lsx_vst(p0, output, 112); + __lsx_vst(q0, output, 128); + __lsx_vst(q1, output, 144); + __lsx_vst(q2, output, 160); + __lsx_vst(q3, output, 176); + __lsx_vst(q4, output, 192); + __lsx_vst(q5, output, 208); + __lsx_vst(q6, output, 224); + __lsx_vst(q7, output, 240); +} + +static void vp9_transpose_8x16_to_16x8(uint8_t *input, uint8_t *output, + ptrdiff_t out_pitch) +{ + __m128i p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + ptrdiff_t out_pitch2 = out_pitch << 1; + ptrdiff_t out_pitch3 = out_pitch2 + out_pitch; + ptrdiff_t out_pitch4 = out_pitch2 << 1; + + DUP4_ARG2(__lsx_vld, input, 0, input, 16, input, 32, input, 48, + p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, input, 64, input, 80, input, 96, input, 112, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, input, 128, input, 144, input, 160, input, 176, + q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, input, 192, input, 208, input, 224, input, 240, + q4, q5, q6, q7); + LSX_TRANSPOSE16x8_B(p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, + q6, q7, p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o); + LSX_ST_8(p7_o, p6_o, p5_o, p4_o, p3_o, p2_o, p1_o, p0_o, + output, out_pitch, out_pitch2, out_pitch3, out_pitch4); +} + +static void vp9_transpose_16x16(uint8_t *input, int32_t in_stride, + uint8_t *output, int32_t out_stride) +{ + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i row8, row9, row10, row11, row12, row13, row14, row15; + __m128i tmp0, tmp1, tmp4, tmp5, tmp6, tmp7; + __m128i tmp2, tmp3; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + int32_t in_stride2 = in_stride << 1; + int32_t in_stride3 = in_stride2 + in_stride; + int32_t in_stride4 = in_stride2 << 1; + int32_t out_stride2 = out_stride << 1; + int32_t out_stride3 = out_stride2 + out_stride; + int32_t out_stride4 = out_stride2 << 1; + + LSX_LD_8(input, in_stride, in_stride2, in_stride3, in_stride4, + row0, row1, row2, row3, row4, row5, row6, row7); + input += in_stride4; + LSX_LD_8(input, in_stride, in_stride2, in_stride3, in_stride4, + row8, row9, row10, row11, row12, row13, row14, row15); + + LSX_TRANSPOSE16x8_B(row0, row1, row2, row3, row4, row5, row6, row7, + row8, row9, row10, row11, row12, row13, row14, row15, + p7, p6, p5, p4, p3, p2, p1, p0); + + /* transpose 16x8 matrix into 8x16 */ + /* total 8 intermediate register and 32 instructions */ + q7 = __lsx_vpackod_d(row8, row0); + q6 = __lsx_vpackod_d(row9, row1); + q5 = __lsx_vpackod_d(row10, row2); + q4 = __lsx_vpackod_d(row11, row3); + q3 = __lsx_vpackod_d(row12, row4); + q2 = __lsx_vpackod_d(row13, row5); + q1 = __lsx_vpackod_d(row14, row6); + q0 = __lsx_vpackod_d(row15, row7); + + DUP2_ARG2(__lsx_vpackev_b, q6, q7, q4, q5, tmp0, tmp1); + DUP2_ARG2(__lsx_vpackod_b, q6, q7, q4, q5, tmp4, tmp5); + + DUP2_ARG2(__lsx_vpackev_b, q2, q3, q0, q1, q5, q7); + DUP2_ARG2(__lsx_vpackod_b, q2, q3, q0, q1, tmp6, tmp7); + + DUP2_ARG2(__lsx_vpackev_h, tmp1, tmp0, q7, q5, tmp2, tmp3); + q0 = __lsx_vpackev_w(tmp3, tmp2); + q4 = __lsx_vpackod_w(tmp3, tmp2); + + tmp2 = __lsx_vpackod_h(tmp1, tmp0); + tmp3 = __lsx_vpackod_h(q7, q5); + q2 = __lsx_vpackev_w(tmp3, tmp2); + q6 = __lsx_vpackod_w(tmp3, tmp2); + + DUP2_ARG2(__lsx_vpackev_h, tmp5, tmp4, tmp7, tmp6, tmp2, tmp3); + q1 = __lsx_vpackev_w(tmp3, tmp2); + q5 = __lsx_vpackod_w(tmp3, tmp2); + + tmp2 = __lsx_vpackod_h(tmp5, tmp4); + tmp3 = __lsx_vpackod_h(tmp7, tmp6); + q3 = __lsx_vpackev_w(tmp3, tmp2); + q7 = __lsx_vpackod_w(tmp3, tmp2); + + LSX_ST_8(p7, p6, p5, p4, p3, p2, p1, p0, output, out_stride, + out_stride2, out_stride3, out_stride4); + output += out_stride4; + LSX_ST_8(q0, q1, q2, q3, q4, q5, q6, q7, output, out_stride, + out_stride2, out_stride3, out_stride4); +} + +static int32_t vp9_vt_lpf_t4_and_t8_8w(uint8_t *src, uint8_t *filter48, + uint8_t *src_org, int32_t pitch_org, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i vec0, vec1, vec2, vec3; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, src, -64, src, -48, src, -32, src, -16, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + flat = __lsx_vilvl_d(zero, flat); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + + src_org -= 2; + __lsx_vstelm_w(vec2, src_org, 0, 0); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 1); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 2); + src_org += pitch_org; + __lsx_vstelm_w(vec2, src_org, 0, 3); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 0); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 1); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 2); + src_org += pitch_org; + __lsx_vstelm_w(vec3, src_org, 0, 3); + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + + /* convert 16 bit output data into 8 bit */ + p2_l = __lsx_vpickev_b(p2_filt8_l, p2_filt8_l); + p1_l = __lsx_vpickev_b(p1_filt8_l, p1_filt8_l); + p0_l = __lsx_vpickev_b(p0_filt8_l, p0_filt8_l); + q0_l = __lsx_vpickev_b(q0_filt8_l, q0_filt8_l); + q1_l = __lsx_vpickev_b(q1_filt8_l, q1_filt8_l); + q2_l = __lsx_vpickev_b(q2_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static int32_t vp9_vt_lpf_t16_8w(uint8_t *dst, uint8_t *dst_org, + ptrdiff_t stride, + uint8_t *filter48) +{ + __m128i zero = __lsx_vldi(0); + __m128i filter8, flat, flat2; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 tmp0_l, tmp1_l; + __m128i out_l; + uint8_t *dst_tmp = dst - 128; + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, + dst_tmp, 48, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp, 64, dst_tmp, 80, dst_tmp, 96, + dst_tmp, 112, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, dst, 64, dst, 80, dst, 96, dst, 112, q4, q5, q6, q7); + + flat = __lsx_vld(filter48, 96); + + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + __m128i vec0, vec1, vec2, vec3, vec4; + + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, + filter48, 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + + dst_org -= 3; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 7); + return 1; + } else { + dst -= 7 * 16; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + + out_l =__lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l =__lsx_vpickev_b(out_l, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vstelm_d(p6, dst, 0, 0); + dst += 16; + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vstelm_d(p5, dst, 0, 0); + dst += 16; + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vstelm_d(p4, dst, 0, 0); + dst += 16; + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vstelm_d(p3, dst, 0, 0); + dst += 16; + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((v8i16) tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vstelm_d(filter8, dst, 0, 0); + dst += 16; + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vstelm_d(q3, dst, 0, 0); + dst += 16; + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vstelm_d(q4, dst, 0, 0); + dst += 16; + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vstelm_d(q5, dst, 0, 0); + dst += 16; + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + out_l = __lsx_vpickev_b(out_l, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vstelm_d(q6, dst, 0, 0); + + return 0; + } +} + +void ff_loop_filter_h_16_8_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t early_exit = 0; + uint8_t transposed_input[16 * 24] __attribute__ ((aligned(16))); + uint8_t *filter48 = &transposed_input[16 * 16]; + + vp9_transpose_16x8_to_8x16(dst - 8, stride, transposed_input); + + early_exit = vp9_vt_lpf_t4_and_t8_8w((transposed_input + 16 * 8), + &filter48[0], dst, stride, + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + early_exit = vp9_vt_lpf_t16_8w((transposed_input + 16 * 8), dst, stride, + &filter48[0]); + + if (0 == early_exit) { + vp9_transpose_8x16_to_16x8(transposed_input, dst - 8, stride); + } + } +} + +static int32_t vp9_vt_lpf_t4_and_t8_16w(uint8_t *dst, uint8_t *filter48, + uint8_t *dst_org, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + ptrdiff_t stride2 = stride << 1; + ptrdiff_t stride3 = stride2 + stride; + ptrdiff_t stride4 = stride2 << 1; + __m128i p3, p2, p1, p0, q3, q2, q1, q0; + __m128i p2_out, p1_out, p0_out, q0_out, q1_out, q2_out; + __m128i flat, mask, hev, thresh, b_limit, limit; + __m128i p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l; + __m128i p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h; + __m128i p2_filt8_l, p1_filt8_l, p0_filt8_l; + __m128i q0_filt8_l, q1_filt8_l, q2_filt8_l; + __m128i p2_filt8_h, p1_filt8_h, p0_filt8_h; + __m128i q0_filt8_h, q1_filt8_h, q2_filt8_h; + __m128i vec0, vec1, vec2, vec3, vec4, vec5; + __m128i zero = __lsx_vldi(0); + + /* load vector elements */ + DUP4_ARG2(__lsx_vld, dst, -64, dst, -48, dst, -32, dst, -16, + p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + + thresh = __lsx_vreplgr2vr_b(thresh_ptr); + b_limit = __lsx_vreplgr2vr_b(b_limit_ptr); + limit = __lsx_vreplgr2vr_b(limit_ptr); + + /* mask and hev */ + LPF_MASK_HEV(p3, p2, p1, p0, q0, q1, q2, q3, limit, b_limit, thresh, + hev, mask, flat); + /* flat4 */ + VP9_FLAT4(p3, p2, p0, q0, q2, q3, flat); + /* filter4 */ + VP9_LPF_FILTER4_4W(p1, p0, q0, q1, mask, hev, p1_out, p0_out, q0_out, + q1_out); + + /* if flat is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat)) { + DUP2_ARG2(__lsx_vilvl_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec2 = __lsx_vilvl_h(vec1, vec0); + vec3 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p0_out, p1_out, q1_out, q0_out, vec0, vec1); + vec4 = __lsx_vilvl_h(vec1, vec0); + vec5 = __lsx_vilvh_h(vec1, vec0); + + dst_org -= 2; + __lsx_vstelm_w(vec2, dst_org, 0, 0); + __lsx_vstelm_w(vec2, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec2, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec2, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_w(vec3, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec3, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec3, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_w(vec4, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec4, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec4, dst_org + stride3, 0, 3); + dst_org += stride4; + __lsx_vstelm_w(vec5, dst_org, 0, 0); + __lsx_vstelm_w(vec5, dst_org + stride, 0, 1); + __lsx_vstelm_w(vec5, dst_org + stride2, 0, 2); + __lsx_vstelm_w(vec5, dst_org + stride3, 0, 3); + + return 1; + } else { + DUP4_ARG2(__lsx_vilvl_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_l, p2_l, p1_l, p0_l); + DUP4_ARG2(__lsx_vilvl_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_l, q1_l, q2_l, q3_l); + VP9_FILTER8(p3_l, p2_l, p1_l, p0_l, q0_l, q1_l, q2_l, q3_l, p2_filt8_l, + p1_filt8_l, p0_filt8_l, q0_filt8_l, q1_filt8_l, q2_filt8_l); + DUP4_ARG2(__lsx_vilvh_b, zero, p3, zero, p2, zero, p1, zero, p0, + p3_h, p2_h, p1_h, p0_h); + DUP4_ARG2(__lsx_vilvh_b, zero, q0, zero, q1, zero, q2, zero, q3, + q0_h, q1_h, q2_h, q3_h); + VP9_FILTER8(p3_h, p2_h, p1_h, p0_h, q0_h, q1_h, q2_h, q3_h, p2_filt8_h, + p1_filt8_h, p0_filt8_h, q0_filt8_h, q1_filt8_h, q2_filt8_h); + + /* convert 16 bit output data into 8 bit */ + DUP4_ARG2(__lsx_vpickev_b, p2_filt8_h, p2_filt8_l, p1_filt8_h, + p1_filt8_l, p0_filt8_h, p0_filt8_l, q0_filt8_h, + q0_filt8_l, p2_filt8_l, p1_filt8_l, p0_filt8_l, + q0_filt8_l); + DUP2_ARG2(__lsx_vpickev_b, q1_filt8_h, q1_filt8_l, q2_filt8_h, + q2_filt8_l, q1_filt8_l, q2_filt8_l); + + /* store pixel values */ + p2_out = __lsx_vbitsel_v(p2, p2_filt8_l, flat); + p1_out = __lsx_vbitsel_v(p1_out, p1_filt8_l, flat); + p0_out = __lsx_vbitsel_v(p0_out, p0_filt8_l, flat); + q0_out = __lsx_vbitsel_v(q0_out, q0_filt8_l, flat); + q1_out = __lsx_vbitsel_v(q1_out, q1_filt8_l, flat); + q2_out = __lsx_vbitsel_v(q2, q2_filt8_l, flat); + + __lsx_vst(p2_out, filter48, 0); + __lsx_vst(p1_out, filter48, 16); + __lsx_vst(p0_out, filter48, 32); + __lsx_vst(q0_out, filter48, 48); + __lsx_vst(q1_out, filter48, 64); + __lsx_vst(q2_out, filter48, 80); + __lsx_vst(flat, filter48, 96); + + return 0; + } +} + +static int32_t vp9_vt_lpf_t16_16w(uint8_t *dst, uint8_t *dst_org, + ptrdiff_t stride, + uint8_t *filter48) +{ + __m128i zero = __lsx_vldi(0); + __m128i flat, flat2, filter8; + __m128i p7, p6, p5, p4, p3, p2, p1, p0, q0, q1, q2, q3, q4, q5, q6, q7; + v8u16 p7_l_in, p6_l_in, p5_l_in, p4_l_in; + v8u16 p3_l_in, p2_l_in, p1_l_in, p0_l_in; + v8u16 q7_l_in, q6_l_in, q5_l_in, q4_l_in; + v8u16 q3_l_in, q2_l_in, q1_l_in, q0_l_in; + v8u16 p7_h_in, p6_h_in, p5_h_in, p4_h_in; + v8u16 p3_h_in, p2_h_in, p1_h_in, p0_h_in; + v8u16 q7_h_in, q6_h_in, q5_h_in, q4_h_in; + v8u16 q3_h_in, q2_h_in, q1_h_in, q0_h_in; + v8u16 tmp0_l, tmp1_l, tmp0_h, tmp1_h; + __m128i out_l, out_h; + uint8_t *dst_tmp = dst - 128; + + flat = __lsx_vld(filter48, 96); + + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, + dst_tmp, 48, p7, p6, p5, p4); + DUP4_ARG2(__lsx_vld, dst_tmp, 64, dst_tmp, 80, dst_tmp, 96, + dst_tmp, 112, p3, p2, p1, p0); + DUP4_ARG2(__lsx_vld, dst, 0, dst, 16, dst, 32, dst, 48, q0, q1, q2, q3); + DUP4_ARG2(__lsx_vld, dst, 64, dst, 80, dst, 96, dst, 112, q4, q5, q6, q7); + + VP9_FLAT5(p7, p6, p5, p4, p0, q0, q4, q5, q6, q7, flat, flat2); + + /* if flat2 is zero for all pixels, then no need to calculate other filter */ + if (__lsx_bz_v(flat2)) { + __m128i vec0, vec1, vec2, vec3, vec4, vec5, vec6, vec7; + + DUP4_ARG2(__lsx_vld, filter48, 0, filter48, 16, filter48, 32, + filter48, 48, p2, p1, p0, q0); + DUP2_ARG2(__lsx_vld, filter48, 64, filter48, 80, q1, q2); + + DUP2_ARG2(__lsx_vilvl_b, p1, p2, q0, p0, vec0, vec1); + vec3 = __lsx_vilvl_h(vec1, vec0); + vec4 = __lsx_vilvh_h(vec1, vec0); + DUP2_ARG2(__lsx_vilvh_b, p1, p2, q0, p0, vec0, vec1); + vec6 = __lsx_vilvl_h(vec1, vec0); + vec7 = __lsx_vilvh_h(vec1, vec0); + vec2 = __lsx_vilvl_b(q2, q1); + vec5 = __lsx_vilvh_b(q2, q1); + + dst_org -= 3; + __lsx_vstelm_w(vec3, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec3, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 0); + __lsx_vstelm_h(vec2, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 1); + __lsx_vstelm_h(vec2, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 2); + __lsx_vstelm_h(vec2, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec4, dst_org, 0, 3); + __lsx_vstelm_h(vec2, dst_org, 4, 7); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 0); + __lsx_vstelm_h(vec5, dst_org, 4, 0); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 1); + __lsx_vstelm_h(vec5, dst_org, 4, 1); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 2); + __lsx_vstelm_h(vec5, dst_org, 4, 2); + dst_org += stride; + __lsx_vstelm_w(vec6, dst_org, 0, 3); + __lsx_vstelm_h(vec5, dst_org, 4, 3); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 0); + __lsx_vstelm_h(vec5, dst_org, 4, 4); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 1); + __lsx_vstelm_h(vec5, dst_org, 4, 5); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 2); + __lsx_vstelm_h(vec5, dst_org, 4, 6); + dst_org += stride; + __lsx_vstelm_w(vec7, dst_org, 0, 3); + __lsx_vstelm_h(vec5, dst_org, 4, 7); + + return 1; + } else { + dst -= 7 * 16; + + p7_l_in = (v8u16)__lsx_vilvl_b(zero, p7); + p6_l_in = (v8u16)__lsx_vilvl_b(zero, p6); + p5_l_in = (v8u16)__lsx_vilvl_b(zero, p5); + p4_l_in = (v8u16)__lsx_vilvl_b(zero, p4); + p3_l_in = (v8u16)__lsx_vilvl_b(zero, p3); + p2_l_in = (v8u16)__lsx_vilvl_b(zero, p2); + p1_l_in = (v8u16)__lsx_vilvl_b(zero, p1); + p0_l_in = (v8u16)__lsx_vilvl_b(zero, p0); + q0_l_in = (v8u16)__lsx_vilvl_b(zero, q0); + + tmp0_l = p7_l_in << 3; + tmp0_l -= p7_l_in; + tmp0_l += p6_l_in; + tmp0_l += q0_l_in; + tmp1_l = p6_l_in + p5_l_in; + tmp1_l += p4_l_in; + tmp1_l += p3_l_in; + tmp1_l += p2_l_in; + tmp1_l += p1_l_in; + tmp1_l += p0_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + + p7_h_in = (v8u16)__lsx_vilvh_b(zero, p7); + p6_h_in = (v8u16)__lsx_vilvh_b(zero, p6); + p5_h_in = (v8u16)__lsx_vilvh_b(zero, p5); + p4_h_in = (v8u16)__lsx_vilvh_b(zero, p4); + p3_h_in = (v8u16)__lsx_vilvh_b(zero, p3); + p2_h_in = (v8u16)__lsx_vilvh_b(zero, p2); + p1_h_in = (v8u16)__lsx_vilvh_b(zero, p1); + p0_h_in = (v8u16)__lsx_vilvh_b(zero, p0); + q0_h_in = (v8u16)__lsx_vilvh_b(zero, q0); + + tmp0_h = p7_h_in << 3; + tmp0_h -= p7_h_in; + tmp0_h += p6_h_in; + tmp0_h += q0_h_in; + tmp1_h = p6_h_in + p5_h_in; + tmp1_h += p4_h_in; + tmp1_h += p3_h_in; + tmp1_h += p2_h_in; + tmp1_h += p1_h_in; + tmp1_h += p0_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + + out_l = __lsx_vpickev_b(out_h, out_l); + p6 = __lsx_vbitsel_v(p6, out_l, flat2); + __lsx_vst(p6, dst, 0); + + /* p5 */ + q1_l_in = (v8u16)__lsx_vilvl_b(zero, q1); + tmp0_l = p5_l_in - p6_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q1_h_in = (v8u16)__lsx_vilvh_b(zero, q1); + tmp0_h = p5_h_in - p6_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p5 = __lsx_vbitsel_v(p5, out_l, flat2); + __lsx_vst(p5, dst, 16); + + /* p4 */ + q2_l_in = (v8u16)__lsx_vilvl_b(zero, q2); + tmp0_l = p4_l_in - p5_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q2_h_in = (v8u16)__lsx_vilvh_b(zero, q2); + tmp0_h = p4_h_in - p5_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p4 = __lsx_vbitsel_v(p4, out_l, flat2); + __lsx_vst(p4, dst, 16*2); + + /* p3 */ + q3_l_in = (v8u16)__lsx_vilvl_b(zero, q3); + tmp0_l = p3_l_in - p4_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q3_h_in = (v8u16)__lsx_vilvh_b(zero, q3); + tmp0_h = p3_h_in - p4_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + p3 = __lsx_vbitsel_v(p3, out_l, flat2); + __lsx_vst(p3, dst, 16*3); + + /* p2 */ + q4_l_in = (v8u16)__lsx_vilvl_b(zero, q4); + filter8 = __lsx_vld(filter48, 0); + tmp0_l = p2_l_in - p3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q4_h_in = (v8u16)__lsx_vilvh_b(zero, q4); + tmp0_h = p2_h_in - p3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*4); + + /* p1 */ + q5_l_in = (v8u16)__lsx_vilvl_b(zero, q5); + filter8 = __lsx_vld(filter48, 16); + tmp0_l = p1_l_in - p2_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q5_h_in = (v8u16)__lsx_vilvh_b(zero, q5); + tmp0_h = p1_h_in - p2_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)(tmp1_h), 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*5); + + /* p0 */ + q6_l_in = (v8u16)__lsx_vilvl_b(zero, q6); + filter8 = __lsx_vld(filter48, 32); + tmp0_l = p0_l_in - p1_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q6_h_in = (v8u16)__lsx_vilvh_b(zero, q6); + tmp0_h = p0_h_in - p1_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*6); + + /* q0 */ + q7_l_in = (v8u16)__lsx_vilvl_b(zero, q7); + filter8 = __lsx_vld(filter48, 48); + tmp0_l = q7_l_in - p0_l_in; + tmp0_l += q0_l_in; + tmp0_l -= p7_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + q7_h_in = (v8u16)__lsx_vilvh_b(zero, q7); + tmp0_h = q7_h_in - p0_h_in; + tmp0_h += q0_h_in; + tmp0_h -= p7_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*7); + + /* q1 */ + filter8 = __lsx_vld(filter48, 64); + tmp0_l = q7_l_in - q0_l_in; + tmp0_l += q1_l_in; + tmp0_l -= p6_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q0_h_in; + tmp0_h += q1_h_in; + tmp0_h -= p6_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*8); + + /* q2 */ + filter8 = __lsx_vld(filter48, 80); + tmp0_l = q7_l_in - q1_l_in; + tmp0_l += q2_l_in; + tmp0_l -= p5_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q1_h_in; + tmp0_h += q2_h_in; + tmp0_h -= p5_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + filter8 = __lsx_vbitsel_v(filter8, out_l, flat2); + __lsx_vst(filter8, dst, 16*9); + + /* q3 */ + tmp0_l = q7_l_in - q2_l_in; + tmp0_l += q3_l_in; + tmp0_l -= p4_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q2_h_in; + tmp0_h += q3_h_in; + tmp0_h -= p4_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q3 = __lsx_vbitsel_v(q3, out_l, flat2); + __lsx_vst(q3, dst, 16*10); + + /* q4 */ + tmp0_l = q7_l_in - q3_l_in; + tmp0_l += q4_l_in; + tmp0_l -= p3_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q3_h_in; + tmp0_h += q4_h_in; + tmp0_h -= p3_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q4 = __lsx_vbitsel_v(q4, out_l, flat2); + __lsx_vst(q4, dst, 16*11); + + /* q5 */ + tmp0_l = q7_l_in - q4_l_in; + tmp0_l += q5_l_in; + tmp0_l -= p2_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q4_h_in; + tmp0_h += q5_h_in; + tmp0_h -= p2_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q5 = __lsx_vbitsel_v(q5, out_l, flat2); + __lsx_vst(q5, dst, 16*12); + + /* q6 */ + tmp0_l = q7_l_in - q5_l_in; + tmp0_l += q6_l_in; + tmp0_l -= p1_l_in; + tmp1_l += tmp0_l; + out_l = __lsx_vsrari_h((__m128i)tmp1_l, 4); + tmp0_h = q7_h_in - q5_h_in; + tmp0_h += q6_h_in; + tmp0_h -= p1_h_in; + tmp1_h += tmp0_h; + out_h = __lsx_vsrari_h((__m128i)tmp1_h, 4); + out_l = __lsx_vpickev_b(out_h, out_l); + q6 = __lsx_vbitsel_v(q6, out_l, flat2); + __lsx_vst(q6, dst, 16*13); + + return 0; + } +} + +void ff_loop_filter_h_16_16_lsx(uint8_t *dst, ptrdiff_t stride, + int32_t b_limit_ptr, + int32_t limit_ptr, + int32_t thresh_ptr) +{ + uint8_t early_exit = 0; + uint8_t transposed_input[16 * 24] __attribute__ ((aligned(16))); + uint8_t *filter48 = &transposed_input[16 * 16]; + + vp9_transpose_16x16((dst - 8), stride, &transposed_input[0], 16); + + early_exit = vp9_vt_lpf_t4_and_t8_16w((transposed_input + 16 * 8), + &filter48[0], dst, stride, + b_limit_ptr, limit_ptr, thresh_ptr); + + if (0 == early_exit) { + early_exit = vp9_vt_lpf_t16_16w((transposed_input + 16 * 8), dst, + stride, &filter48[0]); + + if (0 == early_exit) { + vp9_transpose_16x16(transposed_input, 16, (dst - 8), stride); + } + } +} diff --git a/libavcodec/loongarch/vp9_mc_lsx.c b/libavcodec/loongarch/vp9_mc_lsx.c new file mode 100644 index 0000000000..c6746fd87f --- /dev/null +++ b/libavcodec/loongarch/vp9_mc_lsx.c @@ -0,0 +1,2480 @@ +/* + * 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 "libavcodec/vp9dsp.h" +#include "libavutil/loongarch/loongson_intrinsics.h" +#include "vp9dsp_loongarch.h" + +static const uint8_t mc_filt_mask_arr[16 * 3] = { + /* 8 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + /* 4 width cases */ + 0, 1, 1, 2, 2, 3, 3, 4, 16, 17, 17, 18, 18, 19, 19, 20, + /* 4 width cases */ + 8, 9, 9, 10, 10, 11, 11, 12, 24, 25, 25, 26, 26, 27, 27, 28 +}; + + +#define HORIZ_8TAP_4WID_4VECS_FILT(_src0, _src1, _src2, _src3, \ + _mask0, _mask1, _mask2, _mask3, \ + _filter0, _filter1, _filter2, _filter3, \ + _out0, _out1) \ +{ \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _reg0, _reg1, _reg2, _reg3; \ + \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask0, _src3, _src2, _mask0, \ + _tmp0, _tmp1); \ + DUP2_ARG2(__lsx_vdp2_h_b, _tmp0, _filter0, _tmp1, _filter0, _reg0, _reg1); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask1, _src3, _src2, _mask1, \ + _tmp2, _tmp3); \ + DUP2_ARG3(__lsx_vdp2add_h_b, _reg0, _tmp2, _filter1, _reg1, _tmp3, \ + _filter1, _reg0, _reg1); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask2, _src3, _src2, _mask2, \ + _tmp4, _tmp5); \ + DUP2_ARG2(__lsx_vdp2_h_b, _tmp4, _filter2, _tmp5, _filter2, _reg2, _reg3); \ + DUP2_ARG3(__lsx_vshuf_b, _src1, _src0, _mask3, _src3, _src2, _mask3, \ + _tmp6, _tmp7); \ + DUP2_ARG3(__lsx_vdp2add_h_b, _reg2, _tmp6, _filter3, _reg3, _tmp7, \ + _filter3, _reg2, _reg3); \ + DUP2_ARG2(__lsx_vsadd_h, _reg0, _reg2, _reg1, _reg3, _out0, _out1); \ +} + +#define HORIZ_8TAP_8WID_4VECS_FILT(_src0, _src1, _src2, _src3, \ + _mask0, _mask1, _mask2, _mask3, \ + _filter0, _filter1, _filter2, _filter3, \ + _out0, _out1, _out2, _out3) \ +{ \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3, _tmp4, _tmp5, _tmp6, _tmp7; \ + __m128i _reg0, _reg1, _reg2, _reg3, _reg4, _reg5, _reg6, _reg7; \ + \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask0, _src1, _src1, _mask0, _src2,\ + _src2, _mask0, _src3, _src3, _mask0, _tmp0, _tmp1, _tmp2, _tmp3);\ + DUP4_ARG2(__lsx_vdp2_h_b, _tmp0, _filter0, _tmp1, _filter0, _tmp2, \ + _filter0, _tmp3, _filter0, _reg0, _reg1, _reg2, _reg3); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask2, _src1, _src1, _mask2, _src2,\ + _src2, _mask2, _src3, _src3, _mask2, _tmp0, _tmp1, _tmp2, _tmp3);\ + DUP4_ARG2(__lsx_vdp2_h_b, _tmp0, _filter2, _tmp1, _filter2, _tmp2, \ + _filter2, _tmp3, _filter2, _reg4, _reg5, _reg6, _reg7); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask1, _src1, _src1, _mask1, _src2,\ + _src2, _mask1, _src3, _src3, _mask1, _tmp4, _tmp5, _tmp6, _tmp7);\ + DUP4_ARG3(__lsx_vdp2add_h_b, _reg0, _tmp4, _filter1, _reg1, _tmp5, \ + _filter1, _reg2, _tmp6, _filter1, _reg3, _tmp7, _filter1, _reg0, \ + _reg1, _reg2, _reg3); \ + DUP4_ARG3(__lsx_vshuf_b, _src0, _src0, _mask3, _src1, _src1, _mask3, _src2,\ + _src2, _mask3, _src3, _src3, _mask3, _tmp4, _tmp5, _tmp6, _tmp7);\ + DUP4_ARG3(__lsx_vdp2add_h_b, _reg4, _tmp4, _filter3, _reg5, _tmp5, \ + _filter3, _reg6, _tmp6, _filter3, _reg7, _tmp7, _filter3, _reg4, \ + _reg5, _reg6, _reg7); \ + DUP4_ARG2(__lsx_vsadd_h, _reg0, _reg4, _reg1, _reg5, _reg2, _reg6, _reg3, \ + _reg7, _out0, _out1, _out2, _out3); \ +} + +#define FILT_8TAP_DPADD_S_H(_reg0, _reg1, _reg2, _reg3, \ + _filter0, _filter1, _filter2, _filter3) \ +( { \ + __m128i _vec0, _vec1; \ + \ + _vec0 = __lsx_vdp2_h_b(_reg0, _filter0); \ + _vec0 = __lsx_vdp2add_h_b(_vec0, _reg1, _filter1); \ + _vec1 = __lsx_vdp2_h_b(_reg2, _filter2); \ + _vec1 = __lsx_vdp2add_h_b(_vec1, _reg3, _filter3); \ + _vec0 = __lsx_vsadd_h(_vec0, _vec1); \ + \ + _vec0; \ +} ) + +#define HORIZ_8TAP_FILT(_src0, _src1, _mask0, _mask1, _mask2, _mask3, \ + _filt_h0, _filt_h1, _filt_h2, _filt_h3) \ +( { \ + __m128i _tmp0, _tmp1, _tmp2, _tmp3; \ + __m128i _out; \ + \ + DUP4_ARG3(__lsx_vshuf_b, _src1, _src0, _mask0, _src1, _src0, _mask1, _src1,\ + _src0, _mask2, _src1, _src0, _mask3, _tmp0, _tmp1, _tmp2, _tmp3);\ + _out = FILT_8TAP_DPADD_S_H(_tmp0, _tmp1, _tmp2, _tmp3, _filt_h0, _filt_h1, \ + _filt_h2, _filt_h3); \ + _out = __lsx_vsrari_h(_out, 7); \ + _out = __lsx_vsat_h(_out, 7); \ + \ + _out; \ +} ) + +#define LSX_LD_4(_src, _stride, _src0, _src1, _src2, _src3) \ +{ \ + _src0 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src1 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src2 = __lsx_vld(_src, 0); \ + _src += _stride; \ + _src3 = __lsx_vld(_src, 0); \ +} + +static void common_hz_8t_4x4_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out, out0, out1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1); + out = __lsx_vssrarni_b_h(out1, out0, 7); + out = __lsx_vxori_b(out, 128); + __lsx_vstelm_w(out, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out, dst, 0, 3); +} + +static void common_hz_8t_4x8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + uint8_t *_src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out1, dst, 0, 3); +} + +static void common_hz_8t_4w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + if (height == 4) { + common_hz_8t_4x4_lsx(src, src_stride, dst, dst_stride, filter); + } else if (height == 8) { + common_hz_8t_4x8_lsx(src, src_stride, dst, dst_stride, filter); + } +} + +static void common_hz_8t_8x4_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); +} + +static void common_hz_8t_8x8mult_lsx(const 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 = height >> 2; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + uint8_t* _src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + } +} + +static void common_hz_8t_8w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, int32_t height) +{ + if (height == 4) { + common_hz_8t_8x4_lsx(src, src_stride, dst, dst_stride, filter); + } else { + common_hz_8t_8x8mult_lsx(src, src_stride, dst, dst_stride, + filter, height); + } +} + +static void common_hz_8t_16w_lsx(const 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 = height >> 1; + int32_t stride = src_stride << 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + const uint8_t* _src = src + src_stride; + DUP2_ARG2(__lsx_vld, src, 0, _src, 0, src0, src2); + DUP2_ARG2(__lsx_vld, src, 8, _src, 8, src1, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + dst += dst_stride; + __lsx_vst(out1, dst, 0); + dst += dst_stride; + src += stride; + } +} + +static void common_hz_8t_32w_lsx(const 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 = height >> 1; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + + dst += dst_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + dst += dst_stride; + } +} + +static void common_hz_8t_64w_lsx(const 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 = height; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (; loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 32, src, 48, src0, src2); + src3 = __lsx_vld(src, 56); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vst(out0, dst, 32); + __lsx_vst(out1, dst, 48); + src += src_stride; + dst += dst_stride; + } +} + +static void common_vt_8t_4w_lsx(const 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 = height >> 2; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i reg0, reg1, reg2, reg3, reg4; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, tmp0, + tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, tmp4, tmp5); + DUP2_ARG2(__lsx_vilvl_d, tmp3, tmp0, tmp4, tmp1, reg0, reg1); + reg2 = __lsx_vilvl_d(tmp5, tmp2); + DUP2_ARG2(__lsx_vxori_b, reg0, 128, reg1, 128, reg0, reg1); + reg2 = __lsx_vxori_b(reg2, 128); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, reg3, reg4); + DUP2_ARG2(__lsx_vxori_b, reg3, 128, reg4, 128, reg3, reg4); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, reg3, filter0, filter1, + filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg1, reg2, reg3, reg4, filter0, filter1, + filter2, filter3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + reg0 = reg2; + reg1 = reg3; + reg2 = reg4; + src6 = src10; + } +} + +static void common_vt_8t_8w_lsx(const 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 = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1, out2, out3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, tmp0, filter0, filter1, + filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, tmp1, filter0, filter1, + filter2, filter3); + out2 = FILT_8TAP_DPADD_S_H(reg1, reg2, tmp0, tmp2, filter0, filter1, + filter2, filter3); + out3 = FILT_8TAP_DPADD_S_H(reg4, reg5, tmp1, tmp3, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + reg0 = reg2; + reg1 = tmp0; + reg2 = tmp2; + reg3 = reg5; + reg4 = tmp1; + reg5 = tmp3; + src6 = src10; + } +} + +static void common_vt_8t_16w_lsx(const 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 = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, src9, + src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, src10, src9, + src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, filter1, + filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, filter1, + filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, filter1, + filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, filter1, + filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, filter1, + filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, filter1, + filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, filter1, + filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst, 0); + dst += dst_stride; + __lsx_vst(tmp1, dst, 0); + dst += dst_stride; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } +} + +static void common_vt_8t_16w_mult_lsx(const 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 cnt = width >> 4; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + for (;cnt--;) { + uint32_t loop_cnt = height >> 2; + + src_tmp = _src; + dst_tmp = dst; + + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src5, src6); + src_tmp += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, + src10, src9, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, + src10, src9, src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vst(tmp0, dst_tmp, 0); + __lsx_vstx(tmp1, dst_tmp, dst_stride); + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + __lsx_vstx(tmp0, dst_tmp, dst_stride2); + __lsx_vstx(tmp1, dst_tmp, dst_stride3); + dst_tmp += dst_stride4; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } + _src += 16; + dst += 16; + } +} + +static void common_vt_8t_32w_lsx(const 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_mult_lsx(src, src_stride, dst, dst_stride, filter, height, 32); +} + +static void common_vt_8t_64w_lsx(const 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_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 64); +} + +static void common_hv_8ht_8vt_4w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i out0, out1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3 - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, 4, + filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + 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_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + tmp0 = HORIZ_8TAP_FILT(src0, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp2 = HORIZ_8TAP_FILT(src2, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = HORIZ_8TAP_FILT(src4, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG3(__lsx_vshuf_b, tmp2, tmp0, shuff, tmp4, tmp2, shuff, tmp1, tmp3); + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP2_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp2 = __lsx_vpackev_b(tmp5, tmp4); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + tmp3 = HORIZ_8TAP_FILT(src7, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = __lsx_vshuf_b(tmp3, tmp5, shuff); + tmp4 = __lsx_vpackev_b(tmp3, tmp4); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp4, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src1 = HORIZ_8TAP_FILT(src9, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vshuf_b(src1, tmp3, shuff); + src0 = __lsx_vpackev_b(src1, src0); + out1 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp4, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + tmp5 = src1; + tmp0 = tmp2; + tmp1 = tmp4; + tmp2 = src0; + } +} + +static void common_hv_8ht_8vt_8w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3 - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + 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_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + src0 = HORIZ_8TAP_FILT(src0, src0, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = HORIZ_8TAP_FILT(src1, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = HORIZ_8TAP_FILT(src2, src2, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src3 = HORIZ_8TAP_FILT(src3, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src4 = HORIZ_8TAP_FILT(src4, src4, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src5 = HORIZ_8TAP_FILT(src5, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src6 = HORIZ_8TAP_FILT(src6, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP4_ARG2(__lsx_vpackev_b, src1, src0, src3, src2, src5, src4, + src2, src1, tmp0, tmp1, tmp2, tmp4); + DUP2_ARG2(__lsx_vpackev_b, src4, src3, src6, src5, tmp5, tmp6); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + src7 = HORIZ_8TAP_FILT(src7, src7, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp3 = __lsx_vpackev_b(src7, src6); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp3, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src8 = HORIZ_8TAP_FILT(src8, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vpackev_b(src8, src7); + out1 = FILT_8TAP_DPADD_S_H(tmp4, tmp5, tmp6, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src9 = HORIZ_8TAP_FILT(src9, src9, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = __lsx_vpackev_b(src9, src8); + src3 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp3, src1, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src10 = HORIZ_8TAP_FILT(src10, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src2 = __lsx_vpackev_b(src10, src9); + src4 = FILT_8TAP_DPADD_S_H(tmp5, tmp6, src0, src2, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, src4, src3, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src6 = src10; + tmp0 = tmp2; + tmp1 = tmp3; + tmp2 = src1; + tmp4 = tmp6; + tmp5 = src0; + tmp6 = src2; + } +} + +static void common_hv_8ht_8vt_16w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_32w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 4; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_64w_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 8; multiple8_cnt--;) { + common_hv_8ht_8vt_8w_lsx(src, src_stride, dst, dst_stride, filter_horiz, + filter_vert, height); + src += 8; + dst += 8; + } +} + +static void copy_width8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + + for (;cnt--;) { + src0 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src1 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src2 = __lsx_vldrepl_d(src, 0); + src += src_stride; + src3 = __lsx_vldrepl_d(src, 0); + src += src_stride; + __lsx_vstelm_d(src0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src2, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(src3, dst, 0, 0); + dst += dst_stride; + } +} + +static void copy_width16_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t *_src = (uint8_t*)src; + + for (;cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + __lsx_vst(src0, dst, 0); + __lsx_vstx(src1, dst, dst_stride); + __lsx_vstx(src2, dst, dst_stride2); + __lsx_vstx(src3, dst, dst_stride3); + dst += dst_stride4; + } +} + +static void copy_width32_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *src_tmp1 = (uint8_t*)src; + uint8_t *dst_tmp1 = dst; + uint8_t *src_tmp2 = src_tmp1 + 16; + uint8_t *dst_tmp2 = dst_tmp1 + 16; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + + for (;cnt--;) { + src0 = __lsx_vld(src_tmp1, 0); + DUP2_ARG2(__lsx_vldx, src_tmp1, src_stride, src_tmp1, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp1, src_stride3); + src_tmp1 += src_stride4; + + src4 = __lsx_vld(src_tmp2, 0); + DUP2_ARG2(__lsx_vldx, src_tmp2, src_stride, src_tmp2, src_stride2, + src5, src6); + src7 = __lsx_vldx(src_tmp2, src_stride3); + src_tmp2 += src_stride4; + + __lsx_vst(src0, dst_tmp1, 0); + __lsx_vstx(src1, dst_tmp1, dst_stride); + __lsx_vstx(src2, dst_tmp1, dst_stride2); + __lsx_vstx(src3, dst_tmp1, dst_stride3); + dst_tmp1 += dst_stride4; + __lsx_vst(src4, dst_tmp2, 0); + __lsx_vstx(src5, dst_tmp2, dst_stride); + __lsx_vstx(src6, dst_tmp2, dst_stride2); + __lsx_vstx(src7, dst_tmp2, dst_stride3); + dst_tmp2 += dst_stride4; + } +} + +static void copy_width64_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + + for (;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_vld, src, 0, src, 16, src, 32, src, 48, + src8, src9, src10, src11); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src12, src13, src14, src15); + src += src_stride; + __lsx_vst(src0, dst, 0); + __lsx_vst(src1, dst, 16); + __lsx_vst(src2, dst, 32); + __lsx_vst(src3, dst, 48); + dst += dst_stride; + __lsx_vst(src4, dst, 0); + __lsx_vst(src5, dst, 16); + __lsx_vst(src6, dst, 32); + __lsx_vst(src7, dst, 48); + dst += dst_stride; + __lsx_vst(src8, dst, 0); + __lsx_vst(src9, dst, 16); + __lsx_vst(src10, dst, 32); + __lsx_vst(src11, dst, 48); + dst += dst_stride; + __lsx_vst(src12, dst, 0); + __lsx_vst(src13, dst, 16); + __lsx_vst(src14, dst, 32); + __lsx_vst(src15, dst, 48); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_4x4_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1; + __m128i dst0, dst1, dst2, dst3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp0, tmp1); + dst0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + dst3 = __lsx_vldrepl_w(dst_tmp, 0); + dst0 = __lsx_vilvl_w(dst1, dst0); + dst1 = __lsx_vilvl_w(dst3, dst2); + dst0 = __lsx_vilvl_d(dst1, dst0); + tmp0 = __lsx_vssrarni_b_h(tmp1, tmp0, 7); + tmp0 = __lsx_vxori_b(tmp0, 128); + dst0 = __lsx_vavgr_bu(tmp0, dst0); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 3); +} + +static void common_hz_8t_and_aver_dst_4x8_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter) +{ + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, tmp0, tmp1, tmp2, tmp3; + __m128i dst0, dst1; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + src += src_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + tmp0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp0 = __lsx_vilvl_w(tmp1, tmp0); + tmp1 = __lsx_vilvl_w(tmp3, tmp2); + dst0 = __lsx_vilvl_d(tmp1, tmp0); + + tmp0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_w(dst_tmp, 0); + tmp0 = __lsx_vilvl_w(tmp1, tmp0); + tmp1 = __lsx_vilvl_w(tmp3, tmp2); + dst1 = __lsx_vilvl_d(tmp1, tmp0); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp0, tmp1); + LSX_LD_4(src, src_stride, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_4WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, mask3, + filter0, filter1, filter2, filter3, tmp2, tmp3); + DUP4_ARG3(__lsx_vssrarni_b_h, tmp0, tmp0, 7, tmp1, tmp1, 7, tmp2, tmp2, 7, + tmp3, tmp3, 7, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, dst0, tmp1, dst1, dst0, dst1); + __lsx_vstelm_w(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst0, dst, 0, 3); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(dst1, dst, 0, 3); +} + +static void common_hz_8t_and_aver_dst_4w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + if (height == 4) { + common_hz_8t_and_aver_dst_4x4_lsx(src, src_stride, dst, dst_stride, filter); + } else if (height == 8) { + common_hz_8t_and_aver_dst_4x8_lsx(src, src_stride, dst, dst_stride, filter); + } +} + +static void common_hz_8t_and_aver_dst_8w_lsx(const 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 = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i dst0, dst1, dst2, dst3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride2 + src_stride; + int32_t src_stride4 = src_stride2 << 1; + uint8_t *_src = (uint8_t*)src - 3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3,filter0, filter1, filter2, filter3, tmp0, tmp1, tmp2, tmp3); + dst0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + dst3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, dst1, dst0, dst3, dst2, dst0, dst1); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, dst0, tmp1, dst1, dst0, dst1); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 1); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_16w_lsx(const 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 = height >> 1; + int32_t dst_stride2 = dst_stride << 1; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, dst0, dst1, dst2, dst3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;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; + dst0 = __lsx_vld(dst_tmp, 0); + dst1 = __lsx_vldx(dst_tmp, dst_stride); + dst_tmp += dst_stride2; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, src2, + mask0, src3, src3, mask0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, src2, + mask1, src3, src3, mask1, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, src2, + mask2, src3, src3, mask2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, src2, src2, + mask3, src3, src3, mask3, tmp12, tmp13, tmp14, tmp15); + DUP4_ARG2(__lsx_vdp2_h_b, tmp0, filter0, tmp1, filter0, tmp2, filter0, tmp3, + filter0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vdp2_h_b, tmp8, filter2, tmp9, filter2, tmp10, filter2, tmp11, + filter2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp0, tmp4, filter1, tmp1, tmp5, filter1, tmp2, + tmp6, filter1, tmp3, tmp7, filter1, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp8, tmp12, filter3, tmp9, tmp13, filter3, tmp10, + tmp14, filter3, tmp11, tmp15, filter3, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vsadd_h, tmp0, tmp4, tmp1, tmp5, tmp2, tmp6, tmp3, tmp7, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, dst2, dst3); + DUP2_ARG2(__lsx_vxori_b, dst2, 128, dst3, 128, dst2, dst3); + DUP2_ARG2(__lsx_vavgr_bu, dst0, dst2, dst1, dst3, dst0, dst1); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + dst += dst_stride2; + } +} + +static void common_hz_8t_and_aver_dst_32w_lsx(const 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 = height; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3, dst0, dst1; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + __m128i tmp8, tmp9, tmp10, tmp11, tmp12, tmp13, tmp14, tmp15; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + src += src_stride; + DUP2_ARG2(__lsx_vld, dst_tmp, 0, dst, 16, dst0, dst1); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask0, src1, src1, mask0, src2, + src2, mask0, src3, src3, mask0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask1, src1, src1, mask1, src2, + src2, mask1, src3, src3, mask1, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask2, src1, src1, mask2, src2, + src2, mask2, src3, src3, mask2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vshuf_b, src0, src0, mask3, src1, src1, mask3, src2, + src2, mask3, src3, src3, mask3, tmp12, tmp13, tmp14, tmp15); + DUP4_ARG2(__lsx_vdp2_h_b, tmp0, filter0, tmp1, filter0, tmp2, filter0, + tmp3, filter0, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG2(__lsx_vdp2_h_b, tmp8, filter2, tmp9, filter2, tmp10, filter2, + tmp11, filter2, tmp8, tmp9, tmp10, tmp11); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp0, tmp4, filter1, tmp1, tmp5, filter1, + tmp2, tmp6, filter1, tmp3, tmp7, filter1, tmp0, tmp1, tmp2, tmp3); + DUP4_ARG3(__lsx_vdp2add_h_b, tmp8, tmp12, filter3, tmp9, tmp13, filter3, + tmp10, tmp14, filter3, tmp11, tmp15, filter3, tmp4, tmp5, tmp6, tmp7); + DUP4_ARG2(__lsx_vsadd_h, tmp0, tmp4, tmp1, tmp5, tmp2, tmp6, tmp3, tmp7, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp1, tmp0, 7, tmp3, tmp2, 7, tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + DUP2_ARG2(__lsx_vavgr_bu, dst0, tmp0, dst1, tmp1, dst0, dst1); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + dst += dst_stride; + } +} + +static void common_hz_8t_and_aver_dst_64w_lsx(const 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 = height; + __m128i src0, src1, src2, src3; + __m128i filter0, filter1, filter2, filter3; + __m128i mask0, mask1, mask2, mask3; + __m128i out0, out1, out2, out3, dst0, dst1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + src -= 3; + DUP2_ARG2(__lsx_vaddi_bu, mask0, 2, mask0, 4, mask1, mask2); + mask3 = __lsx_vaddi_bu(mask0, 6); + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + for (;loop_cnt--;) { + DUP2_ARG2(__lsx_vld, src, 0, src, 16, src0, src2); + src3 = __lsx_vld(src, 24); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP2_ARG2(__lsx_vld, dst, 0, dst, 16, dst0, dst1); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, dst0, out1, dst1, out0, out1); + __lsx_vst(out0, dst, 0); + __lsx_vst(out1, dst, 16); + + DUP2_ARG2(__lsx_vld, src, 32, src, 48, src0, src2); + src3 = __lsx_vld(src, 56); + src1 = __lsx_vshuf_b(src2, src0, shuff); + DUP2_ARG2(__lsx_vld, dst, 32, dst, 48, dst0, dst1); + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + HORIZ_8TAP_8WID_4VECS_FILT(src0, src1, src2, src3, mask0, mask1, mask2, + mask3, filter0, filter1, filter2, filter3, out0, out1, out2, out3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, dst0, out1, dst1, out0, out1); + __lsx_vst(out0, dst, 32); + __lsx_vst(out1, dst, 48); + src += src_stride; + dst += dst_stride; + } +} + +static void common_vt_8t_and_aver_dst_4w_lsx(const 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 = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i reg0, reg1, reg2, reg3, reg4; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, tmp4, tmp5); + DUP2_ARG2(__lsx_vilvl_d, tmp3, tmp0, tmp4, tmp1, reg0, reg1); + reg2 = __lsx_vilvl_d(tmp5, tmp2); + DUP2_ARG2(__lsx_vxori_b, reg0, 128, reg1, 128, reg0, reg1); + reg2 = __lsx_vxori_b(reg2, 128); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src0 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src1 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_w, src1, src0, src3, src2, src0, src1); + src0 = __lsx_vilvl_d(src1, src0); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, reg3, reg4); + DUP2_ARG2(__lsx_vxori_b, reg3, 128, reg4, 128, reg3, reg4); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, reg3, filter0, + filter1, filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg1, reg2, reg3, reg4, filter0, + filter1, filter2, filter3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + out0 = __lsx_vavgr_bu(out0, src0); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + reg0 = reg2; + reg1 = reg3; + reg2 = reg4; + src6 = src10; + } +} + +static void common_vt_8t_and_aver_dst_8w_lsx(const 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 = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i tmp0, tmp1, tmp2, tmp3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i filter0, filter1, filter2, filter3; + __m128i out0, out1, out2, out3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, + src1, reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, src1, src0, src3, src2, src0, src1); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, src10, + src9, tmp0, tmp1, tmp2, tmp3); + out0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, tmp0, filter0, + filter1, filter2, filter3); + out1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, tmp1, filter0, + filter1, filter2, filter3); + out2 = FILT_8TAP_DPADD_S_H(reg1, reg2, tmp0, tmp2, filter0, + filter1, filter2, filter3); + out3 = FILT_8TAP_DPADD_S_H(reg4, reg5, tmp1, tmp3, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, out3, out2, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + DUP2_ARG2(__lsx_vavgr_bu, out0, src0, out1, src1, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + reg0 = reg2; + reg1 = tmp0; + reg2 = tmp2; + reg3 = reg5; + reg4 = tmp1; + reg5 = tmp3; + src6 = src10; + } +} + +static void common_vt_8t_and_aver_dst_16w_mult_lsx(const 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; + uint32_t cnt = width >> 4; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filter0, filter1, filter2, filter3; + __m128i reg0, reg1, reg2, reg3, reg4, reg5; + __m128i reg6, reg7, reg8, reg9, reg10, reg11; + __m128i tmp0, tmp1, tmp2, tmp3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t *_src = (uint8_t*)src - src_stride3; + + DUP4_ARG2(__lsx_vldrepl_h, filter, 0, filter, 2, filter, 4, filter, 6, + filter0, filter1, filter2, filter3); + for (;cnt--;) { + uint32_t loop_cnt = height >> 2; + uint8_t *dst_reg = dst; + + src_tmp = _src; + src0 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src1, src2); + src3 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + src4 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src5, src6); + src_tmp += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + DUP4_ARG2(__lsx_vilvl_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg0, reg1, reg2, reg3); + DUP2_ARG2(__lsx_vilvl_b, src4, src3, src6, src5, reg4, reg5); + DUP4_ARG2(__lsx_vilvh_b, src1, src0, src3, src2, src5, src4, src2, src1, + reg6, reg7, reg8, reg9); + DUP2_ARG2(__lsx_vilvh_b, src4, src3, src6, src5, reg10, reg11); + + for (;loop_cnt--;) { + src7 = __lsx_vld(src_tmp, 0); + DUP2_ARG2(__lsx_vldx, src_tmp, src_stride, src_tmp, src_stride2, + src8, src9); + src10 = __lsx_vldx(src_tmp, src_stride3); + src_tmp += src_stride4; + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, + 128, src7, src8, src9, src10); + DUP4_ARG2(__lsx_vilvl_b, src7, src6, src8, src7, src9, src8, + src10, src9, src0, src1, src2, src3); + DUP4_ARG2(__lsx_vilvh_b, src7, src6, src8, src7, src9, src8, + src10, src9, src4, src5, src7, src8); + tmp0 = FILT_8TAP_DPADD_S_H(reg0, reg1, reg2, src0, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg3, reg4, reg5, src1, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg6, reg7, reg8, src4, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg9, reg10, reg11, src5, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + tmp2 = __lsx_vld(dst_reg, 0); + tmp3 = __lsx_vldx(dst_reg, dst_stride); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, tmp2, tmp1, tmp3, tmp0, tmp1); + __lsx_vst(tmp0, dst_reg, 0); + __lsx_vstx(tmp1, dst_reg, dst_stride); + tmp0 = FILT_8TAP_DPADD_S_H(reg1, reg2, src0, src2, filter0, + filter1, filter2, filter3); + tmp1 = FILT_8TAP_DPADD_S_H(reg4, reg5, src1, src3, filter0, + filter1, filter2, filter3); + tmp2 = FILT_8TAP_DPADD_S_H(reg7, reg8, src4, src7, filter0, + filter1, filter2, filter3); + tmp3 = FILT_8TAP_DPADD_S_H(reg10, reg11, src5, src8, filter0, + filter1, filter2, filter3); + DUP2_ARG3(__lsx_vssrarni_b_h, tmp2, tmp0, 7, tmp3, tmp1, 7, + tmp0, tmp1); + DUP2_ARG2(__lsx_vxori_b, tmp0, 128, tmp1, 128, tmp0, tmp1); + tmp2 = __lsx_vldx(dst_reg, dst_stride2); + tmp3 = __lsx_vldx(dst_reg, dst_stride3); + DUP2_ARG2(__lsx_vavgr_bu, tmp0, tmp2, tmp1, tmp3, tmp0, tmp1); + __lsx_vstx(tmp0, dst_reg, dst_stride2); + __lsx_vstx(tmp1, dst_reg, dst_stride3); + dst_reg += dst_stride4; + + reg0 = reg2; + reg1 = src0; + reg2 = src2; + reg3 = reg5; + reg4 = src1; + reg5 = src3; + reg6 = reg8; + reg7 = src4; + reg8 = src7; + reg9 = reg11; + reg10 = src5; + reg11 = src8; + src6 = src10; + } + _src += 16; + dst += 16; + } +} + +static void common_vt_8t_and_aver_dst_16w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 16); +} + +static void common_vt_8t_and_aver_dst_32w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 32); +} + +static void common_vt_8t_and_aver_dst_64w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + const int8_t *filter, + int32_t height) +{ + common_vt_8t_and_aver_dst_16w_mult_lsx(src, src_stride, dst, dst_stride, + filter, height, 64); +} + +static void common_hv_8ht_8vt_and_aver_dst_4w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + __m128i out0, out1; + __m128i shuff = {0x0F0E0D0C0B0A0908, 0x1716151413121110}; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - 3 - src_stride3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 16); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + 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_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + tmp0 = HORIZ_8TAP_FILT(src0, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp2 = HORIZ_8TAP_FILT(src2, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = HORIZ_8TAP_FILT(src4, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp5 = HORIZ_8TAP_FILT(src5, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + DUP2_ARG3(__lsx_vshuf_b, tmp2, tmp0, shuff, tmp4, tmp2, shuff, tmp1, tmp3); + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP2_ARG2(__lsx_vpackev_b, tmp1, tmp0, tmp3, tmp2, tmp0, tmp1); + tmp2 = __lsx_vpackev_b(tmp5, tmp4); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src2 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src3 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src4 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + src5 = __lsx_vldrepl_w(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_w, src3, src2, src5, src4, src2, src3); + src2 = __lsx_vilvl_d(src3, src2); + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + tmp3 = HORIZ_8TAP_FILT(src7, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp4 = __lsx_vshuf_b(tmp3, tmp5, shuff); + tmp4 = __lsx_vpackev_b(tmp3, tmp4); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp4, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src1 = HORIZ_8TAP_FILT(src9, src10, mask0, mask1, mask2, mask3, + filt_hz0, filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vshuf_b(src1, tmp3, shuff); + src0 = __lsx_vpackev_b(src1, src0); + out1 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp4, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + out0 = __lsx_vssrarni_b_h(out1, out0, 7); + out0 = __lsx_vxori_b(out0, 128); + out0 = __lsx_vavgr_bu(out0, src2); + __lsx_vstelm_w(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 2); + dst += dst_stride; + __lsx_vstelm_w(out0, dst, 0, 3); + dst += dst_stride; + + tmp5 = src1; + tmp0 = tmp2; + tmp1 = tmp4; + tmp2 = src0; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_8w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + uint32_t loop_cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, src10; + __m128i filt_hz0, filt_hz1, filt_hz2, filt_hz3; + __m128i filt_vt0, filt_vt1, filt_vt2, filt_vt3; + __m128i mask0, mask1, mask2, mask3; + __m128i tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; + __m128i out0, out1; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + uint8_t* _src = (uint8_t*)src - 3 - src_stride3; + + mask0 = __lsx_vld(mc_filt_mask_arr, 0); + DUP4_ARG2(__lsx_vldrepl_h, filter_horiz, 0, filter_horiz, 2, filter_horiz, + 4, filter_horiz, 6, filt_hz0, filt_hz1, filt_hz2, filt_hz3); + 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_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + src4 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src5, src6); + _src += src_stride3; + DUP4_ARG2(__lsx_vxori_b, src0, 128, src1, 128, src2, 128, src3, 128, + src0, src1, src2, src3); + DUP2_ARG2(__lsx_vxori_b, src4, 128, src5, 128, src4, src5); + src6 = __lsx_vxori_b(src6, 128); + + src0 = HORIZ_8TAP_FILT(src0, src0, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = HORIZ_8TAP_FILT(src1, src1, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = HORIZ_8TAP_FILT(src2, src2, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src3 = HORIZ_8TAP_FILT(src3, src3, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src4 = HORIZ_8TAP_FILT(src4, src4, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src5 = HORIZ_8TAP_FILT(src5, src5, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src6 = HORIZ_8TAP_FILT(src6, src6, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + + DUP4_ARG2(__lsx_vldrepl_h, filter_vert, 0, filter_vert, 2, filter_vert, 4, + filter_vert, 6, filt_vt0, filt_vt1, filt_vt2, filt_vt3); + DUP4_ARG2(__lsx_vpackev_b, src1, src0, src3, src2, src5, src4, + src2, src1, tmp0, tmp1, tmp2, tmp4); + DUP2_ARG2(__lsx_vpackev_b, src4, src3, src6, src5, tmp5, tmp6); + + for (;loop_cnt--;) { + src7 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src8, src9); + src10 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + DUP4_ARG2(__lsx_vxori_b, src7, 128, src8, 128, src9, 128, src10, 128, + src7, src8, src9, src10); + src7 = HORIZ_8TAP_FILT(src7, src7, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + tmp3 = __lsx_vpackev_b(src7, src6); + out0 = FILT_8TAP_DPADD_S_H(tmp0, tmp1, tmp2, tmp3, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src8 = HORIZ_8TAP_FILT(src8, src8, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src0 = __lsx_vpackev_b(src8, src7); + out1 = FILT_8TAP_DPADD_S_H(tmp4, tmp5, tmp6, src0, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src9 = HORIZ_8TAP_FILT(src9, src9, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src1 = __lsx_vpackev_b(src9, src8); + src3 = FILT_8TAP_DPADD_S_H(tmp1, tmp2, tmp3, src1, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + src10 = HORIZ_8TAP_FILT(src10, src10, mask0, mask1, mask2, mask3, filt_hz0, + filt_hz1, filt_hz2, filt_hz3); + src2 = __lsx_vpackev_b(src10, src9); + src4 = FILT_8TAP_DPADD_S_H(tmp5, tmp6, src0, src2, filt_vt0, filt_vt1, + filt_vt2, filt_vt3); + DUP2_ARG3(__lsx_vssrarni_b_h, out1, out0, 7, src4, src3, 7, out0, out1); + DUP2_ARG2(__lsx_vxori_b, out0, 128, out1, 128, out0, out1); + src5 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src7 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src8 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + src9 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, src7, src5, src9, src8, src5, src7); + DUP2_ARG2(__lsx_vavgr_bu, out0, src5, out1, src7, out0, out1); + __lsx_vstelm_d(out0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(out1, dst, 0, 1); + dst += dst_stride; + + src6 = src10; + tmp0 = tmp2; + tmp1 = tmp3; + tmp2 = src1; + tmp4 = tmp6; + tmp5 = src0; + tmp6 = src2; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_16w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 2; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_32w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 4; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void common_hv_8ht_8vt_and_aver_dst_64w_lsx(const uint8_t *src, + int32_t src_stride, + uint8_t *dst, + int32_t dst_stride, + const int8_t *filter_horiz, + const int8_t *filter_vert, + int32_t height) +{ + int32_t multiple8_cnt; + + for (multiple8_cnt = 8; multiple8_cnt--;) { + common_hv_8ht_8vt_and_aver_dst_8w_lsx(src, src_stride, dst, dst_stride, + filter_horiz, filter_vert, + height); + + src += 8; + dst += 8; + } +} + +static void avg_width8_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, dst0, dst1; + __m128i tmp0, tmp1, tmp2, tmp3; + + for (;cnt--;) { + tmp0 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp1 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp2 = __lsx_vldrepl_d(src, 0); + src += src_stride; + tmp3 = __lsx_vldrepl_d(src, 0); + src += src_stride; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, src0, src1); + tmp0 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp1 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp2 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + tmp3 = __lsx_vldrepl_d(dst_tmp, 0); + dst_tmp += dst_stride; + DUP2_ARG2(__lsx_vilvl_d, tmp1, tmp0, tmp3, tmp2, dst0, dst1); + DUP2_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, dst0, dst1); + __lsx_vstelm_d(dst0, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst0, dst, 0, 1); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 0); + dst += dst_stride; + __lsx_vstelm_d(dst1, dst, 0, 1); + dst += dst_stride; + } +} + +static void avg_width16_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + __m128i src0, src1, src2, src3; + __m128i dst0, dst1, dst2, dst3; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + uint8_t* _src = (uint8_t*)src; + + for (;cnt--;) { + src0 = __lsx_vld(_src, 0); + DUP2_ARG2(__lsx_vldx, _src, src_stride, _src, src_stride2, src1, src2); + src3 = __lsx_vldx(_src, src_stride3); + _src += src_stride4; + + dst0 = __lsx_vld(dst, 0); + DUP2_ARG2(__lsx_vldx, dst, dst_stride, dst, dst_stride2, + dst1, dst2); + dst3 = __lsx_vldx(dst, dst_stride3); + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + __lsx_vst(dst0, dst, 0); + __lsx_vstx(dst1, dst, dst_stride); + __lsx_vstx(dst2, dst, dst_stride2); + __lsx_vstx(dst3, dst, dst_stride3); + dst += dst_stride4; + } +} + +static void avg_width32_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *src_tmp1 = (uint8_t*)src; + uint8_t *src_tmp2 = src_tmp1 + 16; + uint8_t *dst_tmp1, *dst_tmp2; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + int32_t src_stride2 = src_stride << 1; + int32_t src_stride3 = src_stride + src_stride2; + int32_t src_stride4 = src_stride2 << 1; + int32_t dst_stride2 = dst_stride << 1; + int32_t dst_stride3 = dst_stride2 + dst_stride; + int32_t dst_stride4 = dst_stride2 << 1; + + dst_tmp1 = dst; + dst_tmp2 = dst + 16; + for (;cnt--;) { + src0 = __lsx_vld(src_tmp1, 0); + DUP2_ARG2(__lsx_vldx, src_tmp1, src_stride, src_tmp1, src_stride2, + src2, src4); + src6 = __lsx_vldx(src_tmp1, src_stride3); + src_tmp1 += src_stride4; + + src1 = __lsx_vld(src_tmp2, 0); + DUP2_ARG2(__lsx_vldx, src_tmp2, src_stride, src_tmp2, src_stride2, + src3, src5); + src7 = __lsx_vldx(src_tmp2, src_stride3); + src_tmp2 += src_stride4; + + dst0 = __lsx_vld(dst_tmp1, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp1, dst_stride, dst_tmp1, dst_stride2, + dst2, dst4); + dst6 = __lsx_vldx(dst_tmp1, dst_stride3); + dst1 = __lsx_vld(dst_tmp2, 0); + DUP2_ARG2(__lsx_vldx, dst_tmp2, dst_stride, dst_tmp2, dst_stride2, + dst3, dst5); + dst7 = __lsx_vldx(dst_tmp2, dst_stride3); + + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, + src6, dst6, src7, dst7, dst4, dst5, dst6, dst7); + __lsx_vst(dst0, dst_tmp1, 0); + __lsx_vstx(dst2, dst_tmp1, dst_stride); + __lsx_vstx(dst4, dst_tmp1, dst_stride2); + __lsx_vstx(dst6, dst_tmp1, dst_stride3); + dst_tmp1 += dst_stride4; + __lsx_vst(dst1, dst_tmp2, 0); + __lsx_vstx(dst3, dst_tmp2, dst_stride); + __lsx_vstx(dst5, dst_tmp2, dst_stride2); + __lsx_vstx(dst7, dst_tmp2, dst_stride3); + dst_tmp2 += dst_stride4; + } +} + +static void avg_width64_lsx(const uint8_t *src, int32_t src_stride, + uint8_t *dst, int32_t dst_stride, + int32_t height) +{ + int32_t cnt = height >> 2; + uint8_t *dst_tmp = dst; + __m128i src0, src1, src2, src3, src4, src5, src6, src7; + __m128i src8, src9, src10, src11, src12, src13, src14, src15; + __m128i dst0, dst1, dst2, dst3, dst4, dst5, dst6, dst7; + __m128i dst8, dst9, dst10, dst11, dst12, dst13, dst14, dst15; + + for (;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_vld, src, 0, src, 16, src, 32, src, 48, + src8, src9, src10, src11); + src += src_stride; + DUP4_ARG2(__lsx_vld, src, 0, src, 16, src, 32, src, 48, + src12, src13, src14, src15); + src += src_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst0, dst1, dst2, dst3); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst4, dst5, dst6, dst7); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst8, dst9, dst10, dst11); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vld, dst_tmp, 0, dst_tmp, 16, dst_tmp, 32, dst_tmp, 48, + dst12, dst13, dst14, dst15); + dst_tmp += dst_stride; + DUP4_ARG2(__lsx_vavgr_bu, src0, dst0, src1, dst1, + src2, dst2, src3, dst3, dst0, dst1, dst2, dst3); + DUP4_ARG2(__lsx_vavgr_bu, src4, dst4, src5, dst5, + src6, dst6, src7, dst7, dst4, dst5, dst6, dst7); + DUP4_ARG2(__lsx_vavgr_bu, src8, dst8, src9, dst9, src10, + dst10, src11, dst11, dst8, dst9, dst10, dst11); + DUP4_ARG2(__lsx_vavgr_bu, src12, dst12, src13, dst13, src14, + dst14, src15, dst15, dst12, dst13, dst14, dst15); + __lsx_vst(dst0, dst, 0); + __lsx_vst(dst1, dst, 16); + __lsx_vst(dst2, dst, 32); + __lsx_vst(dst3, dst, 48); + dst += dst_stride; + __lsx_vst(dst4, dst, 0); + __lsx_vst(dst5, dst, 16); + __lsx_vst(dst6, dst, 32); + __lsx_vst(dst7, dst, 48); + dst += dst_stride; + __lsx_vst(dst8, dst, 0); + __lsx_vst(dst9, dst, 16); + __lsx_vst(dst10, dst, 32); + __lsx_vst(dst11, dst, 48); + dst += dst_stride; + __lsx_vst(dst12, dst, 0); + __lsx_vst(dst13, dst, 16); + __lsx_vst(dst14, dst, 32); + __lsx_vst(dst15, dst, 48); + dst += dst_stride; + } +} + +static const int8_t vp9_subpel_filters_lsx[3][15][8] = { + [FILTER_8TAP_REGULAR] = { + {0, 1, -5, 126, 8, -3, 1, 0}, + {-1, 3, -10, 122, 18, -6, 2, 0}, + {-1, 4, -13, 118, 27, -9, 3, -1}, + {-1, 4, -16, 112, 37, -11, 4, -1}, + {-1, 5, -18, 105, 48, -14, 4, -1}, + {-1, 5, -19, 97, 58, -16, 5, -1}, + {-1, 6, -19, 88, 68, -18, 5, -1}, + {-1, 6, -19, 78, 78, -19, 6, -1}, + {-1, 5, -18, 68, 88, -19, 6, -1}, + {-1, 5, -16, 58, 97, -19, 5, -1}, + {-1, 4, -14, 48, 105, -18, 5, -1}, + {-1, 4, -11, 37, 112, -16, 4, -1}, + {-1, 3, -9, 27, 118, -13, 4, -1}, + {0, 2, -6, 18, 122, -10, 3, -1}, + {0, 1, -3, 8, 126, -5, 1, 0}, + }, [FILTER_8TAP_SHARP] = { + {-1, 3, -7, 127, 8, -3, 1, 0}, + {-2, 5, -13, 125, 17, -6, 3, -1}, + {-3, 7, -17, 121, 27, -10, 5, -2}, + {-4, 9, -20, 115, 37, -13, 6, -2}, + {-4, 10, -23, 108, 48, -16, 8, -3}, + {-4, 10, -24, 100, 59, -19, 9, -3}, + {-4, 11, -24, 90, 70, -21, 10, -4}, + {-4, 11, -23, 80, 80, -23, 11, -4}, + {-4, 10, -21, 70, 90, -24, 11, -4}, + {-3, 9, -19, 59, 100, -24, 10, -4}, + {-3, 8, -16, 48, 108, -23, 10, -4}, + {-2, 6, -13, 37, 115, -20, 9, -4}, + {-2, 5, -10, 27, 121, -17, 7, -3}, + {-1, 3, -6, 17, 125, -13, 5, -2}, + {0, 1, -3, 8, 127, -7, 3, -1}, + }, [FILTER_8TAP_SMOOTH] = { + {-3, -1, 32, 64, 38, 1, -3, 0}, + {-2, -2, 29, 63, 41, 2, -3, 0}, + {-2, -2, 26, 63, 43, 4, -4, 0}, + {-2, -3, 24, 62, 46, 5, -4, 0}, + {-2, -3, 21, 60, 49, 7, -4, 0}, + {-1, -4, 18, 59, 51, 9, -4, 0}, + {-1, -4, 16, 57, 53, 12, -4, -1}, + {-1, -4, 14, 55, 55, 14, -4, -1}, + {-1, -4, 12, 53, 57, 16, -4, -1}, + {0, -4, 9, 51, 59, 18, -4, -1}, + {0, -4, 7, 49, 60, 21, -3, -2}, + {0, -4, 5, 46, 62, 24, -3, -2}, + {0, -4, 4, 43, 63, 26, -2, -2}, + {0, -3, 2, 41, 63, 29, -2, -2}, + {0, -3, 1, 38, 64, 32, -1, -3}, + } +}; + +#define VP9_8TAP_LOONGARCH_LSX_FUNC(SIZE, type, type_idx) \ +void ff_put_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + \ + common_hz_8t_##SIZE##w_lsx(src, srcstride, dst, dststride, filter, h); \ +} \ + \ +void ff_put_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_vt_8t_##SIZE##w_lsx(src, srcstride, dst, dststride, filter, h); \ +} \ + \ +void ff_put_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *hfilter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + const int8_t *vfilter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_hv_8ht_8vt_##SIZE##w_lsx(src, srcstride, dst, dststride, hfilter, \ + vfilter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + \ + common_hz_8t_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, \ + dststride, filter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *filter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_vt_8t_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, dststride, \ + filter, h); \ +} \ + \ +void ff_avg_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + const int8_t *hfilter = vp9_subpel_filters_lsx[type_idx][mx-1]; \ + const int8_t *vfilter = vp9_subpel_filters_lsx[type_idx][my-1]; \ + \ + common_hv_8ht_8vt_and_aver_dst_##SIZE##w_lsx(src, srcstride, dst, \ + dststride, hfilter, \ + vfilter, h); \ +} + +#define VP9_COPY_LOONGARCH_LSX_FUNC(SIZE) \ +void ff_copy##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + \ + copy_width##SIZE##_lsx(src, srcstride, dst, dststride, h); \ +} \ +void ff_avg##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my) \ +{ \ + \ + avg_width##SIZE##_lsx(src, srcstride, dst, dststride, h); \ +} + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, regular, FILTER_8TAP_REGULAR); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, sharp, FILTER_8TAP_SHARP); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, smooth, FILTER_8TAP_SMOOTH); + +VP9_COPY_LOONGARCH_LSX_FUNC(64); +VP9_COPY_LOONGARCH_LSX_FUNC(32); +VP9_COPY_LOONGARCH_LSX_FUNC(16); +VP9_COPY_LOONGARCH_LSX_FUNC(8); + +#undef VP9_8TAP_LOONGARCH_LSX_FUNC +#undef VP9_COPY_LOONGARCH_LSX_FUNC diff --git a/libavcodec/loongarch/vp9dsp_init_loongarch.c b/libavcodec/loongarch/vp9dsp_init_loongarch.c new file mode 100644 index 0000000000..e49625ad5f --- /dev/null +++ b/libavcodec/loongarch/vp9dsp_init_loongarch.c @@ -0,0 +1,130 @@ +/* + * 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 "libavutil/attributes.h" +#include "libavcodec/vp9dsp.h" +#include "vp9dsp_loongarch.h" + +#define init_subpel1(idx1, idx2, idxh, idxv, sz, dir, type) \ + dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][idxh][idxv] = \ + ff_##type##_8tap_smooth_##sz##dir##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][idxh][idxv] = \ + ff_##type##_8tap_regular_##sz##dir##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_SHARP ][idx2][idxh][idxv] = \ + ff_##type##_8tap_sharp_##sz##dir##_lsx; + +#define init_subpel2(idx, idxh, idxv, dir, type) \ + init_subpel1(0, idx, idxh, idxv, 64, dir, type); \ + init_subpel1(1, idx, idxh, idxv, 32, dir, type); \ + init_subpel1(2, idx, idxh, idxv, 16, dir, type); \ + init_subpel1(3, idx, idxh, idxv, 8, dir, type); \ + init_subpel1(4, idx, idxh, idxv, 4, dir, type); + +#define init_subpel3(idx, type) \ + init_subpel2(idx, 1, 0, h, type); \ + init_subpel2(idx, 0, 1, v, type); \ + init_subpel2(idx, 1, 1, hv, type); + +#define init_fpel(idx1, idx2, sz, type) \ + dsp->mc[idx1][FILTER_8TAP_SMOOTH ][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_REGULAR][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_8TAP_SHARP ][idx2][0][0] = ff_##type##sz##_lsx; \ + dsp->mc[idx1][FILTER_BILINEAR ][idx2][0][0] = ff_##type##sz##_lsx; + +#define init_copy(idx, sz) \ + init_fpel(idx, 0, sz, copy); \ + init_fpel(idx, 1, sz, avg); + +#define init_intra_pred1_lsx(tx, sz) \ + dsp->intra_pred[tx][VERT_PRED] = ff_vert_##sz##_lsx; \ + dsp->intra_pred[tx][HOR_PRED] = ff_hor_##sz##_lsx; \ + dsp->intra_pred[tx][DC_PRED] = ff_dc_##sz##_lsx; \ + dsp->intra_pred[tx][LEFT_DC_PRED] = ff_dc_left_##sz##_lsx; \ + dsp->intra_pred[tx][TOP_DC_PRED] = ff_dc_top_##sz##_lsx; \ + dsp->intra_pred[tx][DC_128_PRED] = ff_dc_128_##sz##_lsx; \ + dsp->intra_pred[tx][DC_127_PRED] = ff_dc_127_##sz##_lsx; \ + dsp->intra_pred[tx][DC_129_PRED] = ff_dc_129_##sz##_lsx; \ + dsp->intra_pred[tx][TM_VP8_PRED] = ff_tm_##sz##_lsx; \ + +#define init_intra_pred2_lsx(tx, sz) \ + dsp->intra_pred[tx][DC_PRED] = ff_dc_##sz##_lsx; \ + dsp->intra_pred[tx][LEFT_DC_PRED] = ff_dc_left_##sz##_lsx; \ + dsp->intra_pred[tx][TOP_DC_PRED] = ff_dc_top_##sz##_lsx; \ + dsp->intra_pred[tx][TM_VP8_PRED] = ff_tm_##sz##_lsx; \ + +#define init_idct(tx, nm) \ + dsp->itxfm_add[tx][DCT_DCT] = \ + dsp->itxfm_add[tx][ADST_DCT] = \ + dsp->itxfm_add[tx][DCT_ADST] = \ + dsp->itxfm_add[tx][ADST_ADST] = nm##_add_lsx; + +#define init_itxfm(tx, sz) \ + dsp->itxfm_add[tx][DCT_DCT] = ff_idct_idct_##sz##_add_lsx; + +av_cold void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp) +{ + int cpu_flags = av_get_cpu_flags(); + if (have_lsx(cpu_flags)) + if (bpp == 8) { + init_subpel3(0, put); + init_subpel3(1, avg); + init_copy(0, 64); + init_copy(1, 32); + init_copy(2, 16); + init_copy(3, 8); + init_intra_pred1_lsx(TX_16X16, 16x16); + init_intra_pred1_lsx(TX_32X32, 32x32); + init_intra_pred2_lsx(TX_4X4, 4x4); + init_intra_pred2_lsx(TX_8X8, 8x8); + init_itxfm(TX_8X8, 8x8); + init_itxfm(TX_16X16, 16x16); + init_idct(TX_32X32, ff_idct_idct_32x32); + dsp->loop_filter_8[0][0] = ff_loop_filter_h_4_8_lsx; + dsp->loop_filter_8[0][1] = ff_loop_filter_v_4_8_lsx; + dsp->loop_filter_8[1][0] = ff_loop_filter_h_8_8_lsx; + dsp->loop_filter_8[1][1] = ff_loop_filter_v_8_8_lsx; + dsp->loop_filter_8[2][0] = ff_loop_filter_h_16_8_lsx; + dsp->loop_filter_8[2][1] = ff_loop_filter_v_16_8_lsx; + + dsp->loop_filter_16[0] = ff_loop_filter_h_16_16_lsx; + dsp->loop_filter_16[1] = ff_loop_filter_v_16_16_lsx; + + dsp->loop_filter_mix2[0][0][0] = ff_loop_filter_h_44_16_lsx; + dsp->loop_filter_mix2[0][0][1] = ff_loop_filter_v_44_16_lsx; + dsp->loop_filter_mix2[0][1][0] = ff_loop_filter_h_48_16_lsx; + dsp->loop_filter_mix2[0][1][1] = ff_loop_filter_v_48_16_lsx; + dsp->loop_filter_mix2[1][0][0] = ff_loop_filter_h_84_16_lsx; + dsp->loop_filter_mix2[1][0][1] = ff_loop_filter_v_84_16_lsx; + dsp->loop_filter_mix2[1][1][0] = ff_loop_filter_h_88_16_lsx; + dsp->loop_filter_mix2[1][1][1] = ff_loop_filter_v_88_16_lsx; + } +} + +#undef init_subpel1 +#undef init_subpel2 +#undef init_subpel3 +#undef init_copy +#undef init_fpel +#undef init_intra_pred1_lsx +#undef init_intra_pred2_lsx +#undef init_idct +#undef init_itxfm diff --git a/libavcodec/loongarch/vp9dsp_loongarch.h b/libavcodec/loongarch/vp9dsp_loongarch.h new file mode 100644 index 0000000000..3cc918a18c --- /dev/null +++ b/libavcodec/loongarch/vp9dsp_loongarch.h @@ -0,0 +1,182 @@ +/* + * 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_VP9DSP_LOONGARCH_H +#define AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H + +#define VP9_8TAP_LOONGARCH_LSX_FUNC(SIZE, type, type_idx) \ +void ff_put_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_put_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_put_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##h_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##v_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg_8tap_##type##_##SIZE##hv_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, \ + ptrdiff_t srcstride, \ + int h, int mx, int my); + +#define VP9_COPY_LOONGARCH_LSX_FUNC(SIZE) \ +void ff_copy##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my); \ + \ +void ff_avg##SIZE##_lsx(uint8_t *dst, ptrdiff_t dststride, \ + const uint8_t *src, ptrdiff_t srcstride, \ + int h, int mx, int my); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, regular, FILTER_8TAP_REGULAR); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, regular, FILTER_8TAP_REGULAR); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, sharp, FILTER_8TAP_SHARP); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, sharp, FILTER_8TAP_SHARP); + +VP9_8TAP_LOONGARCH_LSX_FUNC(64, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(32, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(16, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(8, smooth, FILTER_8TAP_SMOOTH); +VP9_8TAP_LOONGARCH_LSX_FUNC(4, smooth, FILTER_8TAP_SMOOTH); + +VP9_COPY_LOONGARCH_LSX_FUNC(64); +VP9_COPY_LOONGARCH_LSX_FUNC(32); +VP9_COPY_LOONGARCH_LSX_FUNC(16); +VP9_COPY_LOONGARCH_LSX_FUNC(8); + +#undef VP9_8TAP_LOONGARCH_LSX_FUNC +#undef VP9_COPY_LOONGARCH_LSX_FUNC + +void ff_vert_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_vert_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_hor_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_hor_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_left_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_left_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_top_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_top_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_dc_top_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_top_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_128_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_128_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_127_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_127_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_129_16x16_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_dc_129_32x32_lsx(uint8_t *dst, ptrdiff_t stride, + const uint8_t *left, const uint8_t *top); +void ff_tm_4x4_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_8x8_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_16x16_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_tm_32x32_lsx(uint8_t *dst, ptrdiff_t stride, const uint8_t *left, + const uint8_t *top); +void ff_loop_filter_h_16_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_16_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_4_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_4_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_44_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_44_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_8_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_8_8_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_88_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_88_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_84_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_84_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_48_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_48_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_h_16_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_loop_filter_v_16_16_lsx(uint8_t *dst, ptrdiff_t stride, int32_t e, + int32_t i, int32_t h); +void ff_idct_idct_8x8_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); +void ff_idct_idct_16x16_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); +void ff_idct_idct_32x32_add_lsx(uint8_t *dst, ptrdiff_t stride, + int16_t *block, int eob); + +#endif /* AVCODEC_LOONGARCH_VP9DSP_LOONGARCH_H */ diff --git a/libavcodec/mdec.c b/libavcodec/mdec.c index 39efed69b1..007e7fada8 100644 --- a/libavcodec/mdec.c +++ b/libavcodec/mdec.c @@ -34,6 +34,7 @@ #include "bswapdsp.h" #include "idctdsp.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "thread.h" typedef struct MDECContext { diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 1cebb3d76d..04d5026e68 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -155,6 +155,9 @@ static int h264_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) uint8_t *data = NULL; int data_size = 0; + avctx->profile = ff_h264_get_profile(sps); + avctx->level = sps->level_idc; + if ((ret = h2645_ps_to_nalu(sps->data, sps->data_size, &data, &data_size)) < 0) { goto done; } @@ -236,6 +239,9 @@ static int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format) uint8_t *data; int data_size; + avctx->profile = sps->ptl.general_ptl.profile_idc; + avctx->level = sps->ptl.general_ptl.level_idc; + if ((ret = h2645_ps_to_nalu(vps->data, vps->data_size, &vps_data, &vps_data_size)) < 0 || (ret = h2645_ps_to_nalu(sps->data, sps->data_size, &sps_data, &sps_data_size)) < 0 || (ret = h2645_ps_to_nalu(pps->data, pps->data_size, &pps_data, &pps_data_size)) < 0) { diff --git a/libavcodec/mjpeg2jpeg_bsf.c b/libavcodec/mjpeg2jpeg_bsf.c index b30f391bf9..2a972a7c37 100644 --- a/libavcodec/mjpeg2jpeg_bsf.c +++ b/libavcodec/mjpeg2jpeg_bsf.c @@ -65,15 +65,15 @@ static uint8_t *append(uint8_t *buf, const uint8_t *src, int size) static uint8_t *append_dht_segment(uint8_t *buf) { buf = append(buf, dht_segment_head, sizeof(dht_segment_head)); - buf = append(buf, avpriv_mjpeg_bits_dc_luminance + 1, 16); + buf = append(buf, ff_mjpeg_bits_dc_luminance + 1, 16); buf = append(buf, dht_segment_frag, sizeof(dht_segment_frag)); - buf = append(buf, avpriv_mjpeg_val_dc, 12); + buf = append(buf, ff_mjpeg_val_dc, 12); *(buf++) = 0x10; - buf = append(buf, avpriv_mjpeg_bits_ac_luminance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_luminance, 162); + buf = append(buf, ff_mjpeg_bits_ac_luminance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_luminance, 162); *(buf++) = 0x11; - buf = append(buf, avpriv_mjpeg_bits_ac_chrominance + 1, 16); - buf = append(buf, avpriv_mjpeg_val_ac_chrominance, 162); + buf = append(buf, ff_mjpeg_bits_ac_chrominance + 1, 16); + buf = append(buf, ff_mjpeg_val_ac_chrominance, 162); return buf; } diff --git a/libavcodec/mjpeg_parser.c b/libavcodec/mjpeg_parser.c index 16a5902c7c..62b923b625 100644 --- a/libavcodec/mjpeg_parser.c +++ b/libavcodec/mjpeg_parser.c @@ -80,10 +80,10 @@ static int find_frame_end(MJPEGParserContext *m, const uint8_t *buf, int buf_siz pc->frame_start_found=0; pc->state=0; return i-3; + } else if((state>>16)==0xFFD9 && (state&0xFFFF)!=0xFFD8){ + state= 0xFFD900|(state&0xFF); } else if(state<0xFFD00000 || state>0xFFD9FFFF){ m->size= (state&0xFFFF)-1; - if (m->size >= 0xF000) - m->size = 0; } } if(m->size>0){ diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 7f89641660..a735d2337d 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -61,18 +61,18 @@ static int init_default_huffman_tables(MJpegDecodeContext *s) const uint8_t *values; int length; } ht[] = { - { 0, 0, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc, 12 }, - { 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc, 12 }, - { 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, - { 2, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance, 162 }, - { 2, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance, 162 }, + { 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc, 12 }, + { 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc, 12 }, + { 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, + { 2, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance, 162 }, + { 2, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance, 162 }, }; int i, ret; @@ -127,9 +127,7 @@ av_cold int ff_mjpeg_decode_init(AVCodecContext *avctx) s->picture_ptr = s->picture; } - s->pkt = av_packet_alloc(); - if (!s->pkt) - return AVERROR(ENOMEM); + s->pkt = avctx->internal->in_pkt; s->avctx = avctx; ff_blockdsp_init(&s->bdsp, avctx); @@ -2898,14 +2896,14 @@ the_end: break; case 5: av_display_rotation_set(matrix, 90.0); - av_display_matrix_flip(matrix, 0, 1); + av_display_matrix_flip(matrix, 1, 0); break; case 6: av_display_rotation_set(matrix, 90.0); break; case 7: av_display_rotation_set(matrix, -90.0); - av_display_matrix_flip(matrix, 0, 1); + av_display_matrix_flip(matrix, 1, 0); break; case 8: av_display_rotation_set(matrix, -90.0); @@ -2960,8 +2958,6 @@ av_cold int ff_mjpeg_decode_end(AVCodecContext *avctx) } else if (s->picture_ptr) av_frame_unref(s->picture_ptr); - av_packet_free(&s->pkt); - av_frame_free(&s->smv_frame); av_freep(&s->buffer); diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c index 0ade66bc5f..d15b9ece50 100644 --- a/libavcodec/mjpegenc.c +++ b/libavcodec/mjpegenc.c @@ -41,6 +41,15 @@ #include "mjpegenc.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 +74,26 @@ 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->mjpeg_ctx, + &s->intra_scantable, 0, + s->intra_matrix, s->chroma_intra_matrix); + + 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 +214,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 +233,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 @@ -260,11 +288,23 @@ static int alloc_huffman(MpegEncContext *s) av_cold int ff_mjpeg_encode_init(MpegEncContext *s) { - MJpegContext *m; + MJpegContext *const m = &((MJPEGEncContext*)s)->mjpeg; int ret; + s->mjpeg_ctx = m; + av_assert0(s->slice_context_count == 1); + if (s->codec_id == AV_CODEC_ID_AMV || (s->avctx->active_thread_type & FF_THREAD_SLICE)) + 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. */ ret = ff_mjpeg_encode_check_pix_fmt(s->avctx); @@ -276,10 +316,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; @@ -288,20 +324,20 @@ av_cold int ff_mjpeg_encode_init(MpegEncContext *s) // they are needed at least right now for some processes like trellis. ff_mjpeg_build_huffman_codes(m->huff_size_dc_luminance, m->huff_code_dc_luminance, - avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_dc_chrominance, m->huff_code_dc_chrominance, - avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); ff_mjpeg_build_huffman_codes(m->huff_size_ac_luminance, m->huff_code_ac_luminance, - avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); + ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); ff_mjpeg_build_huffman_codes(m->huff_size_ac_chrominance, m->huff_code_ac_chrominance, - avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); init_uni_ac_vlc(m->huff_size_ac_luminance, m->uni_ac_vlc_len); init_uni_ac_vlc(m->huff_size_ac_chrominance, m->uni_chroma_ac_vlc_len); @@ -312,20 +348,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 +409,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 +517,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,14 +617,16 @@ 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" }, +#if FF_API_MJPEG_PRED +{ "pred", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), 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" }, +#endif { "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" }, @@ -615,10 +652,10 @@ const AVCodec ff_mjpeg_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MJPEG (Motion JPEG)"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MJPEG, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, .encode2 = ff_mpv_encode_picture, - .close = ff_mpv_encode_end, + .close = mjpeg_encode_close, .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[]) { @@ -644,10 +681,10 @@ const AVCodec ff_amv_encoder = { .long_name = NULL_IF_CONFIG_SMALL("AMV Video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_AMV, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MJPEGEncContext), .init = ff_mpv_encode_init, .encode2 = amv_encode_picture, - .close = ff_mpv_encode_end, + .close = mjpeg_encode_close, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP, .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE diff --git a/libavcodec/mjpegenc.h b/libavcodec/mjpegenc.h index 2e92511276..a593b67e96 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 c1b842d547..995e2b7670 100644 --- a/libavcodec/mjpegenc_common.c +++ b/libavcodec/mjpegenc_common.c @@ -56,6 +56,7 @@ 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], @@ -63,27 +64,22 @@ static void jpeg_table_header(AVCodecContext *avctx, PutBitContext *p, { 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 */ @@ -110,26 +106,26 @@ 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, avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - size += put_huffman_table(p, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); + size += put_huffman_table(p, 0, 0, ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + size += put_huffman_table(p, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); - size += put_huffman_table(p, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - size += put_huffman_table(p, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + size += put_huffman_table(p, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + size += put_huffman_table(p, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); } AV_WB16(ptr, size); } @@ -192,11 +188,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 +200,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 +213,13 @@ void ff_mjpeg_init_hvsample(AVCodecContext *avctx, int hsample[4], int vsample[4 } void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64]) { - 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 +230,13 @@ 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_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); switch (avctx->codec_id) { case AV_CODEC_ID_MJPEG: put_marker(pb, SOF0 ); break; @@ -310,7 +307,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 +316,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 76c236d835..ac753bf153 100644 --- a/libavcodec/mjpegenc_common.h +++ b/libavcodec/mjpegenc_common.h @@ -27,7 +27,10 @@ #include "idctdsp.h" #include "put_bits.h" +struct MJpegContext; + void ff_mjpeg_encode_picture_header(AVCodecContext *avctx, PutBitContext *pb, + struct MJpegContext *m, ScanTable *intra_scantable, int pred, uint16_t luma_intra_matrix[64], uint16_t chroma_intra_matrix[64]); diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 68c270ef52..29fac54542 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -408,7 +408,9 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) mh.stream_type); return AVERROR_PATCHWELCOME; } - if (mh.channel_modifier_thd_stream0 == THD_CH_MODIFIER_STEREO) + if (mh.channels_thd_stream1 == 2 && + mh.channels_thd_stream2 == 2 && + m->avctx->channels == 2) m->substream[0].mask = AV_CH_LAYOUT_STEREO; if ((substr = (mh.num_substreams > 1))) m->substream[0].mask = AV_CH_LAYOUT_STEREO; @@ -417,7 +419,8 @@ 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; - m->substream[1].mask = mh.channel_layout_thd_stream1; + if (m->avctx->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) { av_log(m->avctx, AV_LOG_DEBUG, "Mono stream with 2 substreams, ignoring 2nd\n"); diff --git a/libavcodec/mlpenc.c b/libavcodec/mlpenc.c index 1cb02f22a9..d8783b6f56 100644 --- a/libavcodec/mlpenc.c +++ b/libavcodec/mlpenc.c @@ -626,7 +626,7 @@ static av_cold int mlp_encode_init(AVCodecContext *avctx) ctx->ch_modifier_thd0 = 0; ctx->ch_modifier_thd1 = 0; ctx->ch_modifier_thd2 = 0; - ctx->channel_arrangement = 0; + ctx->channel_arrangement = 1; break; case AV_CH_LAYOUT_5POINT0_BACK: ctx->ch_modifier_thd0 = 1; diff --git a/libavcodec/mmaldec.c b/libavcodec/mmaldec.c index 8c7d749742..cd645189d9 100644 --- a/libavcodec/mmaldec.c +++ b/libavcodec/mmaldec.c @@ -83,6 +83,8 @@ typedef struct MMALDecodeContext { // libavcodec API can't return new frames, and we have a logical deadlock. // This is avoided by queuing such buffers here. FFBufferEntry *waiting_buffers, *waiting_buffers_tail; + /* Packet used to hold received packets temporarily; not owned by us. */ + AVPacket *pkt; int64_t packets_sent; atomic_int packets_buffered; @@ -355,6 +357,8 @@ static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) MMAL_COMPONENT_T *decoder; int ret = 0; + ctx->pkt = avctx->internal->in_pkt; + bcm_host_init(); if (mmal_vc_init()) { @@ -481,29 +485,19 @@ static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, int is_extradata) { MMALDecodeContext *ctx = avctx->priv_data; - AVBufferRef *buf = NULL; + const AVBufferRef *buf = NULL; int size = 0; uint8_t *data = (uint8_t *)""; uint8_t *start; int ret = 0; if (avpkt->size) { - if (avpkt->buf) { - buf = av_buffer_ref(avpkt->buf); - size = avpkt->size; - data = avpkt->data; - } else { - buf = av_buffer_alloc(avpkt->size); - if (buf) { - memcpy(buf->data, avpkt->data, avpkt->size); - size = buf->size; - data = buf->data; - } - } - if (!buf) { - ret = AVERROR(ENOMEM); + ret = av_packet_make_refcounted(avpkt); + if (ret < 0) goto done; - } + buf = avpkt->buf; + data = avpkt->data; + size = avpkt->size; if (!is_extradata) ctx->packets_sent++; } else { @@ -569,7 +563,7 @@ static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, } while (size); done: - av_buffer_unref(&buf); + av_packet_unref(avpkt); return ret; } @@ -651,10 +645,16 @@ static int ffmal_copy_frame(AVCodecContext *avctx, AVFrame *frame, av_image_fill_arrays(src, linesize, buffer->data + buffer->type->video.offset[0], avctx->pix_fmt, w, h, 1); - av_image_copy(frame->data, frame->linesize, src, linesize, + av_image_copy(frame->data, frame->linesize, (const uint8_t **)src, linesize, avctx->pix_fmt, avctx->width, avctx->height); } + frame->sample_aspect_ratio = avctx->sample_aspect_ratio; + frame->width = avctx->width; + frame->width = avctx->width; + frame->height = avctx->height; + frame->format = avctx->pix_fmt; + frame->pts = buffer->pts == MMAL_TIME_UNKNOWN ? AV_NOPTS_VALUE : buffer->pts; frame->pkt_dts = AV_NOPTS_VALUE; @@ -763,24 +763,26 @@ done: return ret; } -static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) +static int ffmmal_receive_frame(AVCodecContext *avctx, AVFrame *frame) { MMALDecodeContext *ctx = avctx->priv_data; - AVFrame *frame = data; + AVPacket *const avpkt = ctx->pkt; int ret = 0; + int got_frame = 0; if (avctx->extradata_size && !ctx->extradata_sent) { - AVPacket pkt = {0}; - av_init_packet(&pkt); - pkt.data = avctx->extradata; - pkt.size = avctx->extradata_size; + avpkt->data = avctx->extradata; + avpkt->size = avctx->extradata_size; ctx->extradata_sent = 1; - if ((ret = ffmmal_add_packet(avctx, &pkt, 1)) < 0) + if ((ret = ffmmal_add_packet(avctx, avpkt, 1)) < 0) return ret; } - if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) + ret = ff_decode_get_packet(avctx, avpkt); + if (ret == 0) { + if ((ret = ffmmal_add_packet(avctx, avpkt, 0)) < 0) + return ret; + } else if (ret < 0 && !(ret == AVERROR(EAGAIN))) return ret; if ((ret = ffmmal_fill_input_port(avctx)) < 0) @@ -789,7 +791,7 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ffmmal_fill_output_port(avctx)) < 0) return ret; - if ((ret = ffmmal_read_frame(avctx, frame, got_frame)) < 0) + if ((ret = ffmmal_read_frame(avctx, frame, &got_frame)) < 0) return ret; // ffmmal_read_frame() can block for a while. Since the decoder is @@ -801,7 +803,10 @@ static int ffmmal_decode(AVCodecContext *avctx, void *data, int *got_frame, if ((ret = ffmmal_fill_input_port(avctx)) < 0) return ret; - return ret; + if (!got_frame && ret == 0) + return AVERROR(EAGAIN); + else + return ret; } static const AVCodecHWConfigInternal *const mmal_hw_configs[] = { @@ -815,16 +820,14 @@ static const AVOption options[]={ {NULL} }; -#define FFMMAL_DEC_CLASS(NAME) \ - static const AVClass ffmmal_##NAME##_dec_class = { \ - .class_name = "mmal_" #NAME "_dec", \ - .item_name = av_default_item_name, \ - .option = options, \ - .version = LIBAVUTIL_VERSION_INT, \ - }; +static const AVClass ffmmal_dec_class = { + .class_name = "mmal_dec", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; #define FFMMAL_DEC(NAME, ID) \ - FFMMAL_DEC_CLASS(NAME) \ const AVCodec ff_##NAME##_mmal_decoder = { \ .name = #NAME "_mmal", \ .long_name = NULL_IF_CONFIG_SMALL(#NAME " (mmal)"), \ @@ -833,9 +836,9 @@ static const AVOption options[]={ .priv_data_size = sizeof(MMALDecodeContext), \ .init = ffmmal_init_decoder, \ .close = ffmmal_close_decoder, \ - .decode = ffmmal_decode, \ + .receive_frame = ffmmal_receive_frame, \ .flush = ffmmal_flush, \ - .priv_class = &ffmmal_##NAME##_dec_class, \ + .priv_class = &ffmmal_dec_class, \ .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, \ diff --git a/libavcodec/mobiclip.c b/libavcodec/mobiclip.c index 6ea1c3eefa..23d64f76f6 100644 --- a/libavcodec/mobiclip.c +++ b/libavcodec/mobiclip.c @@ -491,7 +491,7 @@ static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, int ret, idx = get_ue_golomb_31(gb); if (idx == 0) { - ret = add_coefficients(avctx, frame, bx, by, size, plane); + return add_coefficients(avctx, frame, bx, by, size, plane); } else if ((unsigned)idx < FF_ARRAY_ELEMS(pframe_block4x4_coefficients_tab)) { int flags = pframe_block4x4_coefficients_tab[idx]; @@ -505,11 +505,10 @@ static int add_pframe_coefficients(AVCodecContext *avctx, AVFrame *frame, flags >>= 1; } } + return 0; } else { - ret = AVERROR_INVALIDDATA; + return AVERROR_INVALIDDATA; } - - return ret; } static int adjust(int x, int size) diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c index 4e14ae5900..825632ca9b 100644 --- a/libavcodec/movtextdec.c +++ b/libavcodec/movtextdec.c @@ -54,37 +54,31 @@ #define RGB_TO_BGR(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff)) typedef struct { - uint16_t fontID; - const char *font; - uint8_t fontsize; - int color; - uint8_t alpha; - int back_color; - uint8_t back_alpha; - uint8_t bold; - uint8_t italic; - uint8_t underline; - int alignment; -} MovTextDefault; - -typedef struct { - uint16_t fontID; + uint16_t font_id; char *font; } FontRecord; typedef struct { - uint16_t style_start; - uint16_t style_end; - uint8_t style_flag; + uint16_t start; + uint16_t end; + uint8_t flags; uint8_t bold; uint8_t italic; uint8_t underline; int color; uint8_t alpha; uint8_t fontsize; - uint16_t style_fontID; + uint16_t font_id; } StyleBox; +typedef struct { + StyleBox style; + const char *font; + int back_color; + uint8_t back_alpha; + int alignment; +} MovTextDefault; + typedef struct { uint16_t hlit_start; uint16_t hlit_end; @@ -108,8 +102,6 @@ typedef struct { MovTextDefault d; uint8_t box_flags; uint16_t style_entries, ftab_entries; - uint64_t tracksize; - int size_var; int readorder; int frame_width; int frame_height; @@ -117,8 +109,8 @@ typedef struct { typedef struct { uint32_t type; - size_t base_size; - int (*decode)(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt); + unsigned base_size; + int (*decode)(const uint8_t *tsmb, MovTextContext *m, uint64_t size); } Box; static void mov_text_cleanup(MovTextContext *m) @@ -137,13 +129,29 @@ static void mov_text_cleanup_ftab(MovTextContext *m) m->ftab_entries = 0; } +static void mov_text_parse_style_record(StyleBox *style, const uint8_t **ptr) +{ + // fontID + style->font_id = bytestream_get_be16(ptr); + // face-style-flags + style->flags = bytestream_get_byte(ptr); + style->bold = !!(style->flags & STYLE_FLAG_BOLD); + style->italic = !!(style->flags & STYLE_FLAG_ITALIC); + style->underline = !!(style->flags & STYLE_FLAG_UNDERLINE); + // fontsize + style->fontsize = bytestream_get_byte(ptr); + // Primary color + style->color = bytestream_get_be24(ptr); + style->color = RGB_TO_BGR(style->color); + style->alpha = bytestream_get_byte(ptr); +} + static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) { const uint8_t *tx3g_ptr = avctx->extradata; int i, j = -1, font_length, remaining = avctx->extradata_size - BOX_SIZE_INITIAL; int8_t v_align, h_align; unsigned ftab_entries; - StyleBox s_default; m->ftab_entries = 0; if (remaining < 0) @@ -180,23 +188,13 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) } // Background Color m->d.back_color = bytestream_get_be24(&tx3g_ptr); + m->d.back_color = RGB_TO_BGR(m->d.back_color); m->d.back_alpha = bytestream_get_byte(&tx3g_ptr); // BoxRecord tx3g_ptr += 8; // StyleRecord tx3g_ptr += 4; - // fontID - m->d.fontID = bytestream_get_be16(&tx3g_ptr); - // face-style-flags - s_default.style_flag = bytestream_get_byte(&tx3g_ptr); - m->d.bold = !!(s_default.style_flag & STYLE_FLAG_BOLD); - m->d.italic = !!(s_default.style_flag & STYLE_FLAG_ITALIC); - m->d.underline = !!(s_default.style_flag & STYLE_FLAG_UNDERLINE); - // fontsize - m->d.fontsize = bytestream_get_byte(&tx3g_ptr); - // Primary color - m->d.color = bytestream_get_be24(&tx3g_ptr); - m->d.alpha = bytestream_get_byte(&tx3g_ptr); + mov_text_parse_style_record(&m->d.style, &tx3g_ptr); // FontRecord // FontRecord Size tx3g_ptr += 4; @@ -218,8 +216,8 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) m->ftab_entries = ftab_entries; for (i = 0; i < m->ftab_entries; i++) { - m->ftab[i].fontID = bytestream_get_be16(&tx3g_ptr); - if (m->ftab[i].fontID == m->d.fontID) + m->ftab[i].font_id = bytestream_get_be16(&tx3g_ptr); + if (m->ftab[i].font_id == m->d.style.font_id) j = i; font_length = bytestream_get_byte(&tx3g_ptr); @@ -241,14 +239,14 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m) return 0; } -static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= TWRP_BOX; m->w.wrap_flag = bytestream_get_byte(&tsmb); return 0; } -static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= HLIT_BOX; m->h.hlit_start = bytestream_get_be16(&tsmb); @@ -256,21 +254,29 @@ static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a return 0; } -static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { m->box_flags |= HCLR_BOX; bytestream_get_buffer(&tsmb, m->c.hlit_color, 4); return 0; } -static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt) +static int styles_equivalent(const StyleBox *a, const StyleBox *b) +{ +#define CMP(field) a->field == b->field + return CMP(bold) && CMP(italic) && CMP(underline) && CMP(color) && + CMP(alpha) && CMP(fontsize) && CMP(font_id); +#undef CMP +} + +static int decode_styl(const uint8_t *tsmb, MovTextContext *m, uint64_t size) { int i; int style_entries = bytestream_get_be16(&tsmb); StyleBox *tmp; // A single style record is of length 12 bytes. - if (m->tracksize + m->size_var + 2 + style_entries * 12 > avpkt->size) + if (2 + style_entries * 12 > size) return -1; tmp = av_realloc_array(m->s, style_entries, sizeof(*m->s)); @@ -283,14 +289,14 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a for(i = 0; i < m->style_entries; i++) { StyleBox *style = &m->s[i]; - style->style_start = bytestream_get_be16(&tsmb); - style->style_end = bytestream_get_be16(&tsmb); - if ( style->style_end < style->style_start - || (i && style->style_start < m->s[i - 1].style_end)) { + style->start = bytestream_get_be16(&tsmb); + style->end = bytestream_get_be16(&tsmb); + if (style->end < style->start || + (i && style->start < m->s[i - 1].end)) { mov_text_cleanup(m); - return AVERROR(ENOMEM); + return AVERROR_INVALIDDATA; } - if (style->style_start == style->style_end) { + if (style->start == style->end) { /* Skip this style as it applies to no character */ tsmb += 8; m->style_entries--; @@ -298,14 +304,20 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *a continue; } - style->style_fontID = bytestream_get_be16(&tsmb); - style->style_flag = bytestream_get_byte(&tsmb); - style->bold = !!(style->style_flag & STYLE_FLAG_BOLD); - style->italic = !!(style->style_flag & STYLE_FLAG_ITALIC); - style->underline = !!(style->style_flag & STYLE_FLAG_UNDERLINE); - style->fontsize = bytestream_get_byte(&tsmb); - style->color = bytestream_get_be24(&tsmb); - style->alpha = bytestream_get_byte(&tsmb); + mov_text_parse_style_record(style, &tsmb); + if (styles_equivalent(style, &m->d.style)) { + /* Skip this style as it is equivalent to the default style */ + m->style_entries--; + i--; + continue; + } else if (i && style->start == style[-1].end && + styles_equivalent(style, &style[-1])) { + /* Merge the two adjacent styles */ + style[-1].end = style->end; + m->style_entries--; + i--; + continue; + } } return 0; } @@ -337,10 +349,11 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, AVCodecContext *avctx) { MovTextContext *m = avctx->priv_data; + const StyleBox *const default_style = &m->d.style; int i = 0; int text_pos = 0; int entry = 0; - int color = m->d.color; + int color = default_style->color; if (text < text_end && m->box_flags & TWRP_BOX) { if (m->w.wrap_flag == 1) { @@ -355,31 +368,31 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, if ((m->box_flags & STYL_BOX) && entry < m->style_entries) { const StyleBox *style = &m->s[entry]; - if (text_pos == style->style_end) { + if (text_pos == style->end) { av_bprintf(buf, "{\\r}"); - color = m->d.color; + color = default_style->color; entry++; style++; } - if (entry < m->style_entries && text_pos == style->style_start) { - if (style->bold ^ m->d.bold) + if (entry < m->style_entries && text_pos == style->start) { + if (style->bold ^ default_style->bold) av_bprintf(buf, "{\\b%d}", style->bold); - if (style->italic ^ m->d.italic) + if (style->italic ^ default_style->italic) av_bprintf(buf, "{\\i%d}", style->italic); - if (style->underline ^ m->d.underline) + if (style->underline ^ default_style->underline) av_bprintf(buf, "{\\u%d}", style->underline); - if (style->fontsize != m->d.fontsize) + if (style->fontsize != default_style->fontsize) av_bprintf(buf, "{\\fs%d}", style->fontsize); - if (style->style_fontID != m->d.fontID) + if (style->font_id != default_style->font_id) for (i = 0; i < m->ftab_entries; i++) { - if (style->style_fontID == m->ftab[i].fontID) + if (style->font_id == m->ftab[i].font_id) av_bprintf(buf, "{\\fn%s}", m->ftab[i].font); } - if (m->d.color != style->color) { + if (default_style->color != style->color) { color = style->color; - av_bprintf(buf, "{\\1c&H%X&}", RGB_TO_BGR(color)); + av_bprintf(buf, "{\\1c&H%X&}", color); } - if (m->d.alpha != style->alpha) + if (default_style->alpha != style->alpha) av_bprintf(buf, "{\\1a&H%02X&}", 255 - style->alpha); } } @@ -400,10 +413,10 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end, } if (text_pos == m->h.hlit_end) { if (m->box_flags & HCLR_BOX) { - av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(m->d.color)); + av_bprintf(buf, "{\\2c&H%X&}", default_style->color); } else { av_bprintf(buf, "{\\1c&H%X&}{\\2c&H%X&}", - RGB_TO_BGR(color), RGB_TO_BGR(m->d.color)); + color, default_style->color); } } } @@ -441,18 +454,19 @@ static int mov_text_init(AVCodecContext *avctx) { MovTextContext *m = avctx->priv_data; ret = mov_text_tx3g(avctx, m); if (ret == 0) { + const StyleBox *const default_style = &m->d.style; if (!m->frame_width || !m->frame_height) { m->frame_width = ASS_DEFAULT_PLAYRESX; m->frame_height = ASS_DEFAULT_PLAYRESY; } return ff_ass_subtitle_header_full(avctx, m->frame_width, m->frame_height, - m->d.font, m->d.fontsize, - (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color), - (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color), - (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), - (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color), - m->d.bold, m->d.italic, m->d.underline, + m->d.font, default_style->fontsize, + (255U - default_style->alpha) << 24 | default_style->color, + (255U - default_style->alpha) << 24 | default_style->color, + (255U - m->d.back_alpha) << 24 | m->d.back_color, + (255U - m->d.back_alpha) << 24 | m->d.back_color, + default_style->bold, default_style->italic, default_style->underline, ASS_DEFAULT_BORDERSTYLE, m->d.alignment); } else return ff_ass_subtitle_header_default(avctx); @@ -465,11 +479,8 @@ static int mov_text_decode_frame(AVCodecContext *avctx, MovTextContext *m = avctx->priv_data; int ret; AVBPrint buf; - char *ptr = avpkt->data; - char *end; - int text_length, tsmb_type, ret_tsmb; - uint64_t tsmb_size; - const uint8_t *tsmb; + const char *ptr = avpkt->data, *end; + int text_length; size_t i; if (!ptr || avpkt->size < 2) @@ -496,49 +507,47 @@ static int mov_text_decode_frame(AVCodecContext *avctx, mov_text_cleanup(m); - tsmb_size = 0; - m->tracksize = 2 + text_length; m->style_entries = 0; m->box_flags = 0; // Note that the spec recommends lines be no longer than 2048 characters. av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - if (text_length + 2 != avpkt->size) { - while (m->tracksize + 8 <= avpkt->size) { - // A box is a minimum of 8 bytes. - tsmb = ptr + m->tracksize - 2; - tsmb_size = AV_RB32(tsmb); - tsmb += 4; - tsmb_type = AV_RB32(tsmb); - tsmb += 4; + if (text_length + 2 < avpkt->size) { + const uint8_t *tsmb = end; + const uint8_t *const tsmb_end = avpkt->data + avpkt->size; + // A box is a minimum of 8 bytes. + while (tsmb_end - tsmb >= 8) { + uint64_t tsmb_size = bytestream_get_be32(&tsmb); + uint32_t tsmb_type = bytestream_get_be32(&tsmb); + int size_var, ret_tsmb; if (tsmb_size == 1) { - if (m->tracksize + 16 > avpkt->size) + if (tsmb_end - tsmb < 8) break; - tsmb_size = AV_RB64(tsmb); - tsmb += 8; - m->size_var = 16; + tsmb_size = bytestream_get_be64(&tsmb); + size_var = 16; } else - m->size_var = 8; + size_var = 8; //size_var is equal to 8 or 16 depending on the size of box - if (tsmb_size == 0) { - av_log(avctx, AV_LOG_ERROR, "tsmb_size is 0\n"); + if (tsmb_size < size_var) { + av_log(avctx, AV_LOG_ERROR, "tsmb_size invalid\n"); return AVERROR_INVALIDDATA; } + tsmb_size -= size_var; - if (tsmb_size > avpkt->size - m->tracksize) + if (tsmb_end - tsmb < tsmb_size) break; for (i = 0; i < box_count; i++) { if (tsmb_type == box_types[i].type) { - if (m->tracksize + m->size_var + box_types[i].base_size > avpkt->size) + if (tsmb_size < box_types[i].base_size) break; - ret_tsmb = box_types[i].decode(tsmb, m, avpkt); + ret_tsmb = box_types[i].decode(tsmb, m, tsmb_size); if (ret_tsmb == -1) break; } } - m->tracksize = m->tracksize + tsmb_size; + tsmb += tsmb_size; } text_to_ass(&buf, ptr, end, avctx); mov_text_cleanup(m); diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c index 2ae5a9bf0b..221cd76fea 100644 --- a/libavcodec/movtextenc.c +++ b/libavcodec/movtextenc.c @@ -84,7 +84,6 @@ typedef struct { uint8_t box_flags; StyleBox d; uint16_t text_pos; - uint16_t byte_count; char **fonts; int font_count; double font_scale_factor; @@ -495,8 +494,10 @@ static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id) static uint16_t find_font_id(MovTextContext *s, const char *name) { - int i; - for (i = 0; i < s->font_count; i++) { + if (!name) + return 1; + + for (int i = 0; i < s->font_count; i++) { if (!strcmp(name, s->fonts[i])) return i + 1; } @@ -584,9 +585,9 @@ static void mov_text_cancel_overrides_cb(void *priv, const char *style_name) mov_text_ass_style_set(s, style); } -static uint16_t utf8_strlen(const char *text, int len) +static unsigned utf8_strlen(const char *text, int len) { - uint16_t i = 0, ret = 0; + unsigned i = 0, ret = 0; while (i < len) { char c = text[i]; if ((c & 0x80) == 0) @@ -606,20 +607,18 @@ static uint16_t utf8_strlen(const char *text, int len) static void mov_text_text_cb(void *priv, const char *text, int len) { - uint16_t utf8_len = utf8_strlen(text, len); + unsigned utf8_len = utf8_strlen(text, len); MovTextContext *s = priv; av_bprint_append_data(&s->buffer, text, len); // If it's not utf-8, just use the byte length s->text_pos += utf8_len ? utf8_len : len; - s->byte_count += len; } static void mov_text_new_line_cb(void *priv, int forced) { MovTextContext *s = priv; - av_bprint_append_data(&s->buffer, "\n", 1); s->text_pos += 1; - s->byte_count += 1; + av_bprint_chars(&s->buffer, '\n', 1); } static const ASSCodesCallbacks mov_text_callbacks = { @@ -640,12 +639,11 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, MovTextContext *s = avctx->priv_data; ASSDialog *dialog; int i, length; - size_t j; - s->byte_count = 0; s->text_pos = 0; s->count = 0; s->box_flags = 0; + av_bprint_clear(&s->buffer); for (i = 0; i < sub->num_rects; i++) { const char *ass = sub->rects[i]->ass; @@ -660,36 +658,30 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, mov_text_dialog(s, dialog); ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text); ff_ass_free_dialog(&dialog); - - for (j = 0; j < box_count; j++) { - box_types[j].encode(s); - } } - AV_WB16(buf, s->byte_count); + if (s->buffer.len > UINT16_MAX) + return AVERROR(ERANGE); + AV_WB16(buf, s->buffer.len); buf += 2; - if (!av_bprint_is_complete(&s->buffer)) { - length = AVERROR(ENOMEM); - goto exit; - } + for (size_t j = 0; j < box_count; j++) + box_types[j].encode(s); - if (!s->buffer.len) { - length = 0; - goto exit; - } + if (!av_bprint_is_complete(&s->buffer)) + return AVERROR(ENOMEM); + + if (!s->buffer.len) + return 0; if (s->buffer.len > bufsize - 3) { av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); - length = AVERROR_BUFFER_TOO_SMALL; - goto exit; + return AVERROR_BUFFER_TOO_SMALL; } memcpy(buf, s->buffer.str, s->buffer.len); length = s->buffer.len + 2; -exit: - av_bprint_clear(&s->buffer); return length; } diff --git a/libavcodec/mp3_header_decompress_bsf.c b/libavcodec/mp3_header_decompress_bsf.c index 44c174c21c..ebf6bde1c2 100644 --- a/libavcodec/mp3_header_decompress_bsf.c +++ b/libavcodec/mp3_header_decompress_bsf.c @@ -22,6 +22,7 @@ #include "libavutil/intreadwrite.h" #include "bsf.h" #include "bsf_internal.h" +#include "defs.h" #include "mpegaudiodecheader.h" #include "mpegaudiodata.h" @@ -67,10 +68,10 @@ static int mp3_header_decompress(AVBSFContext *ctx, AVPacket *out) goto fail; } - sample_rate= avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); //in case sample rate is a little off for(bitrate_index=2; bitrate_index<30; bitrate_index++){ - frame_size = avpriv_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; + frame_size = ff_mpa_bitrate_tab[lsf][2][bitrate_index>>1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index&1); if(frame_size == buf_size + 4) break; diff --git a/libavcodec/mpeg12dec.c b/libavcodec/mpeg12dec.c index 09b2902bca..6ad9fb245c 100644 --- a/libavcodec/mpeg12dec.c +++ b/libavcodec/mpeg12dec.c @@ -33,6 +33,7 @@ #include "libavutil/internal.h" #include "libavutil/mem_internal.h" #include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #include "libavutil/video_enc_params.h" #include "avcodec.h" @@ -69,6 +70,7 @@ typedef struct Mpeg1Context { int rc_buffer_size; AVRational frame_rate_ext; /* MPEG-2 specific framerate modificator */ int sync; /* Did we reach a sync point like a GOP/SEQ/KEYFrame? */ + int closed_gop; int tmpgexs; int first_slice; int extradata_decoded; @@ -1064,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; @@ -1090,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 @@ -1788,13 +1786,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" : "", @@ -2070,10 +2068,7 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) 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); } 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) @@ -2449,7 +2444,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, tc = s-> timecode_frame_start = get_bits(&s->gb, 25); - s->closed_gop = get_bits1(&s->gb); + s1->closed_gop = get_bits1(&s->gb); /* broken_link indicates that after editing the * reference frames of the first B-Frames after GOP I-Frame * are missing (open gop) */ @@ -2460,7 +2455,7 @@ static void mpeg_decode_gop(AVCodecContext *avctx, av_timecode_make_mpeg_tc_string(tcbuf, tc); av_log(s->avctx, AV_LOG_DEBUG, "GOP (%s) closed_gop=%d broken_link=%d\n", - tcbuf, s->closed_gop, broken_link); + tcbuf, s1->closed_gop, broken_link); } } @@ -2694,7 +2689,7 @@ static int decode_chunks(AVCodecContext *avctx, AVFrame *picture, /* Skip B-frames if we do not have reference frames and * GOP is not closed. */ if (s2->pict_type == AV_PICTURE_TYPE_B) { - if (!s2->closed_gop) { + if (!s->closed_gop) { skip_frame = 1; av_log(s2->avctx, AV_LOG_DEBUG, "Skipping B slice due to open GOP\n"); @@ -2831,7 +2826,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, void *data, } #endif - s2->codec_tag = avpriv_toupper4(avctx->codec_tag); + s2->codec_tag = ff_toupper4(avctx->codec_tag); if (s->mpeg_enc_ctx_allocated == 0 && ( s2->codec_tag == AV_RL32("VCR2") || s2->codec_tag == AV_RL32("BW10") )) @@ -2882,6 +2877,7 @@ static void flush(AVCodecContext *avctx) Mpeg1Context *s = avctx->priv_data; s->sync = 0; + s->closed_gop = 0; ff_mpeg_flush(avctx); } diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c index 2fb2232f3c..e28aa809d2 100644 --- a/libavcodec/mpeg12enc.c +++ b/libavcodec/mpeg12enc.c @@ -62,6 +62,21 @@ 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; + + 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 +116,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; @@ -127,8 +143,8 @@ static int find_frame_rate_index(MpegEncContext *s) || 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_ext.num = ext.num; + mpeg12->frame_rate_ext.den = ext.den; } } } @@ -142,8 +158,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,7 +216,7 @@ 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 (find_frame_rate_index(mpeg12) < 0) { if (s->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); @@ -211,24 +228,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 && s->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) { + if (mpeg12->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); + 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,6 +261,7 @@ 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; uint64_t time_code; @@ -339,8 +357,8 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) 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 + 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) { @@ -356,12 +374,13 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) 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); + mpeg12->video_format != VIDEO_FORMAT_UNSPECIFIED); - if (s->seq_disp_ext == 1 || (s->seq_disp_ext == -1 && use_seq_disp_ext)) { + 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, s->video_format); // video_format + 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 @@ -374,17 +393,17 @@ static void mpeg1_encode_sequence_header(MpegEncContext *s) } put_header(s, GOP_START_CODE); - put_bits(&s->pb, 1, s->drop_frame_timecode); // drop frame flag + 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 + - s->timecode_frame_start; + mpeg12->timecode_frame_start; 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) + 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)); @@ -428,6 +447,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); @@ -505,7 +525,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 +571,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 +621,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 +744,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 +773,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 +791,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 +921,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]); @@ -1005,7 +1028,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]); @@ -1032,9 +1055,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 +1097,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 +1112,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; } @@ -1130,7 +1153,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.", \ @@ -1157,9 +1180,9 @@ static const AVOption mpeg1_options[] = { 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" }, @@ -1180,7 +1203,7 @@ static const AVOption mpeg2_options[] = { #undef LEVEL FF_MPV_COMMON_OPTS #if FF_API_MPEGVIDEO_OPTS - { "mpeg_quant", "Deprecated, does nothing", OFFSET(mpeg_quant), + { "mpeg_quant", "Deprecated, does nothing", FF_MPV_OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 1, VE | AV_OPT_FLAG_DEPRECATED }, FF_MPV_DEPRECATED_MATRIX_OPT #endif @@ -1204,7 +1227,7 @@ const AVCodec ff_mpeg1video_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG1VIDEO, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, @@ -1221,7 +1244,7 @@ const AVCodec ff_mpeg2video_encoder = { .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_MPEG2VIDEO, - .priv_data_size = sizeof(MpegEncContext), + .priv_data_size = sizeof(MPEG12EncContext), .init = encode_init, .encode2 = ff_mpv_encode_picture, .close = ff_mpv_encode_end, diff --git a/libavcodec/mpeg4audio.c b/libavcodec/mpeg4audio.c index be50de9052..ed72a80f6d 100644 --- a/libavcodec/mpeg4audio.c +++ b/libavcodec/mpeg4audio.c @@ -57,13 +57,6 @@ static int parse_config_ALS(GetBitContext *gb, MPEG4AudioConfig *c, void *logctx return 0; } -/* XXX: make sure to update the copies in the different encoders if you change - * this table */ -const int avpriv_mpeg4audio_sample_rates[16] = { - 96000, 88200, 64000, 48000, 44100, 32000, - 24000, 22050, 16000, 12000, 11025, 8000, 7350 -}; - const uint8_t ff_mpeg4audio_channels[14] = { 0, 1, // mono (1/0) @@ -93,7 +86,7 @@ static inline int get_sample_rate(GetBitContext *gb, int *index) { *index = get_bits(gb, 4); return *index == 0x0f ? get_bits(gb, 24) : - avpriv_mpeg4audio_sample_rates[*index]; + ff_mpeg4audio_sample_rates[*index]; } int ff_mpeg4audio_get_config_gb(MPEG4AudioConfig *c, GetBitContext *gb, diff --git a/libavcodec/mpeg4audio.h b/libavcodec/mpeg4audio.h index 3187df68d2..c486a3ddef 100644 --- a/libavcodec/mpeg4audio.h +++ b/libavcodec/mpeg4audio.h @@ -27,7 +27,6 @@ #include "libavutil/attributes.h" #include "get_bits.h" -#include "internal.h" #include "put_bits.h" typedef struct MPEG4AudioConfig { @@ -45,7 +44,7 @@ typedef struct MPEG4AudioConfig { int frame_length_short; } MPEG4AudioConfig; -extern av_export_avcodec const int avpriv_mpeg4audio_sample_rates[16]; +extern const int ff_mpeg4audio_sample_rates[16]; extern const uint8_t ff_mpeg4audio_channels[14]; /** diff --git a/libavcodec/mpeg4audio_sample_rates.c b/libavcodec/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..b5ceb59c6e --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "mpeg4audio_sample_rates.h" diff --git a/libavcodec/mpeg4audio_sample_rates.h b/libavcodec/mpeg4audio_sample_rates.h new file mode 100644 index 0000000000..0b8caa6d76 --- /dev/null +++ b/libavcodec/mpeg4audio_sample_rates.h @@ -0,0 +1,30 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_MPEG4AUDIO_SAMPLE_RATES_H +#define AVCODEC_MPEG4AUDIO_SAMPLE_RATES_H + +const int ff_mpeg4audio_sample_rates[16] = { + 96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, 7350 +}; +#endif diff --git a/libavcodec/mpeg4data.h b/libavcodec/mpeg4data.h index 30179d9801..c5a2b14721 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 3db6f85153..87d9c9996e 100644 --- a/libavcodec/mpeg4video.h +++ b/libavcodec/mpeg4video.h @@ -27,7 +27,6 @@ #include "get_bits.h" #include "mpegvideo.h" -#include "rl.h" // shapes #define RECT_SHAPE 0 @@ -118,40 +117,6 @@ typedef struct Mpeg4DecContext { 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); @@ -160,7 +125,8 @@ void ff_mpeg4_pred_ac(MpegEncContext *s, int16_t *block, int n, 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); +int ff_mpeg4_decode_picture_header(Mpeg4DecContext *ctx, GetBitContext *gb, + int header, int parse_only); void ff_mpeg4_encode_video_packet_header(MpegEncContext *s); void ff_mpeg4_clean_buffers(MpegEncContext *s); void ff_mpeg4_stuffing(PutBitContext *pbc); @@ -172,7 +138,6 @@ 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); diff --git a/libavcodec/mpeg4video_parser.c b/libavcodec/mpeg4video_parser.c index c68c966259..1f89bae490 100644 --- a/libavcodec/mpeg4video_parser.c +++ b/libavcodec/mpeg4video_parser.c @@ -100,13 +100,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 +129,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 0000000000..b20096067a --- /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 34b050db28..737689b35b 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -34,6 +34,7 @@ #include "mpegvideo.h" #include "mpegvideodata.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "h263.h" #include "profiles.h" #include "thread.h" @@ -56,6 +57,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, @@ -2844,7 +2847,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 +3022,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,11 +3076,11 @@ 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, @@ -3095,6 +3105,8 @@ 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) */ @@ -3214,11 +3226,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 +3276,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 +3387,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) @@ -3513,6 +3501,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, @@ -3535,7 +3525,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) diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c index b77653d453..8871d83281 100644 --- a/libavcodec/mpeg4videoenc.c +++ b/libavcodec/mpeg4videoenc.c @@ -28,6 +28,7 @@ #include "mpegvideo.h" #include "h263.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "profiles.h" /* The uni_DCtab_* tables below contain unified bits+length tables to encode DC diff --git a/libavcodec/mpegaudiodata.c b/libavcodec/mpegaudiodata.c index 0569281109..669590908f 100644 --- a/libavcodec/mpegaudiodata.c +++ b/libavcodec/mpegaudiodata.c @@ -26,19 +26,6 @@ #include "mpegaudiodata.h" - -const uint16_t avpriv_mpa_bitrate_tab[2][3][15] = { - { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, - {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, - {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, - { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} - } -}; - -const uint16_t avpriv_mpa_freq_tab[3] = { 44100, 48000, 32000 }; - /*******************************************************/ /* layer 2 tables */ diff --git a/libavcodec/mpegaudiodata.h b/libavcodec/mpegaudiodata.h index 0a425ef6a8..a4148a1ffe 100644 --- a/libavcodec/mpegaudiodata.h +++ b/libavcodec/mpegaudiodata.h @@ -31,14 +31,13 @@ #include "config.h" -#include "internal.h" #include "vlc.h" #define MODE_EXT_MS_STEREO 2 #define MODE_EXT_I_STEREO 1 -extern av_export_avcodec const uint16_t avpriv_mpa_bitrate_tab[2][3][15]; -extern av_export_avcodec const uint16_t avpriv_mpa_freq_tab[3]; +extern const uint16_t ff_mpa_bitrate_tab[2][3][15]; +extern const uint16_t ff_mpa_freq_tab[3]; extern const int ff_mpa_sblimit_table[5]; extern const int ff_mpa_quant_steps[17]; extern const int ff_mpa_quant_bits[17]; diff --git a/libavcodec/mpegaudiodecheader.c b/libavcodec/mpegaudiodecheader.c index 93c5f3d8f8..446a6e29d8 100644 --- a/libavcodec/mpegaudiodecheader.c +++ b/libavcodec/mpegaudiodecheader.c @@ -52,9 +52,9 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->layer = 4 - ((header >> 17) & 3); /* extract frequency */ sample_rate_index = (header >> 10) & 3; - if (sample_rate_index >= FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) + if (sample_rate_index >= FF_ARRAY_ELEMS(ff_mpa_freq_tab)) sample_rate_index = 0; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); sample_rate_index += 3 * (s->lsf + mpeg25); s->sample_rate_index = sample_rate_index; s->error_protection = ((header >> 16) & 1) ^ 1; @@ -75,7 +75,7 @@ int avpriv_mpegaudio_decode_header(MPADecodeHeader *s, uint32_t header) s->nb_channels = 2; if (bitrate_index != 0) { - frame_size = avpriv_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + frame_size = ff_mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; s->bit_rate = frame_size * 1000; switch(s->layer) { case 1: diff --git a/libavcodec/mpegaudioenc_template.c b/libavcodec/mpegaudioenc_template.c index 1df3cc704a..1ffd31f7cb 100644 --- a/libavcodec/mpegaudioenc_template.c +++ b/libavcodec/mpegaudioenc_template.c @@ -95,9 +95,9 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding freq */ s->lsf = 0; for(i=0;i<3;i++) { - if (avpriv_mpa_freq_tab[i] == freq) + if (ff_mpa_freq_tab[i] == freq) break; - if ((avpriv_mpa_freq_tab[i] / 2) == freq) { + if ((ff_mpa_freq_tab[i] / 2) == freq) { s->lsf = 1; break; } @@ -110,12 +110,12 @@ static av_cold int MPA_encode_init(AVCodecContext *avctx) /* encoding bitrate & frequency */ for(i=1;i<15;i++) { - if (avpriv_mpa_bitrate_tab[s->lsf][1][i] == bitrate) + if (ff_mpa_bitrate_tab[s->lsf][1][i] == bitrate) break; } if (i == 15 && !avctx->bit_rate) { i = 14; - bitrate = avpriv_mpa_bitrate_tab[s->lsf][1][i]; + bitrate = ff_mpa_bitrate_tab[s->lsf][1][i]; avctx->bit_rate = bitrate * 1000; } if (i == 15){ diff --git a/libavcodec/mpegaudiotabs.c b/libavcodec/mpegaudiotabs.c new file mode 100644 index 0000000000..eaa380c808 --- /dev/null +++ b/libavcodec/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 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 "mpegaudiotabs.h" diff --git a/libavcodec/mpegaudiotabs.h b/libavcodec/mpegaudiotabs.h new file mode 100644 index 0000000000..671b83848d --- /dev/null +++ b/libavcodec/mpegaudiotabs.h @@ -0,0 +1,39 @@ +/* + * MPEG Audio common tables + * copyright (c) 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_MPEGAUDIOTABS_H +#define AVCODEC_MPEGAUDIOTABS_H + +#include + +const uint16_t ff_mpa_bitrate_tab[2][3][15] = { + { { 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + { 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + { 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }, + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } + } +}; + +const uint16_t ff_mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +#endif diff --git a/libavcodec/mpegpicture.h b/libavcodec/mpegpicture.h index 4bcd666797..a354c2a83c 100644 --- a/libavcodec/mpegpicture.h +++ b/libavcodec/mpegpicture.h @@ -29,6 +29,7 @@ #include "motion_est.h" #include "thread.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; /** diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index ba5b51955e..e9f2fb212a 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -31,21 +31,16 @@ #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 "mpegvideodata.h" -#include "mjpegenc.h" -#include "msmpeg4.h" #include "qpeldsp.h" #include "thread.h" #include "wmv2.h" @@ -348,14 +343,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,17 +371,17 @@ 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]); } if (s->out_format == FMT_H263) { + if (!(s->block32 = av_mallocz(sizeof(*s->block32))) || + !(s->dpcm_macroblock = av_mallocz(sizeof(*s->dpcm_macroblock)))) + return AVERROR(ENOMEM); + s->dpcm_direction = 0; + /* ac values */ if (!FF_ALLOCZ_TYPED_ARRAY(s->ac_val_base, yc_size)) return AVERROR(ENOMEM); @@ -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; @@ -521,152 +503,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); - - if (!s1->first_field) { - s->last_pict_type = s1->pict_type; - if (s1->current_picture_ptr) - s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f->quality; - } - - return 0; -} - /** * Set the given MpegEncContext to common defaults * (same for encoding and decoding). @@ -691,29 +527,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 = avpriv_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; @@ -774,34 +588,53 @@ static int init_context_frame(MpegEncContext *s) !FF_ALLOC_TYPED_ARRAY (s->cplx_tab, mb_array_size) || !FF_ALLOC_TYPED_ARRAY (s->bits_tab, mb_array_size)) return AVERROR(ENOMEM); + +#define ALLOCZ_ARRAYS(p, mult, numb) ((p) = av_calloc(numb, mult * sizeof(*(p)))) + if (s->codec_id == AV_CODEC_ID_MPEG4 || + (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + int16_t (*tmp1)[2]; + uint8_t *tmp2; + if (!(tmp1 = ALLOCZ_ARRAYS(s->b_field_mv_table_base, 8, mv_table_size)) || + !(tmp2 = ALLOCZ_ARRAYS(s->b_field_select_table[0][0], 2 * 4, mv_table_size)) || + !ALLOCZ_ARRAYS(s->p_field_select_table[0], 2 * 2, mv_table_size)) + return AVERROR(ENOMEM); + + s->p_field_select_table[1] = s->p_field_select_table[0] + 2 * mv_table_size; + tmp1 += s->mb_stride + 1; + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + s->b_field_mv_table[i][j][k] = tmp1; + tmp1 += mv_table_size; + } + s->b_field_select_table[i][j] = tmp2; + tmp2 += 2 * mv_table_size; + } + } + } } if (s->codec_id == AV_CODEC_ID_MPEG4 || (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_ME)) { + int16_t (*tmp)[2]; /* interlaced direct mode decoding tables */ - for (i = 0; i < 2; i++) { - int j, k; - for (j = 0; j < 2; j++) { - for (k = 0; k < 2; k++) { - if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_mv_table_base[i][j][k], mv_table_size)) - return AVERROR(ENOMEM); - s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + - s->mb_stride + 1; - } - if (!FF_ALLOCZ_TYPED_ARRAY(s->b_field_select_table [i][j], mv_table_size * 2) || - !FF_ALLOCZ_TYPED_ARRAY(s->p_field_mv_table_base[i][j], mv_table_size)) - return AVERROR(ENOMEM); - s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j] + s->mb_stride + 1; + if (!(tmp = ALLOCZ_ARRAYS(s->p_field_mv_table_base, 4, mv_table_size))) + return AVERROR(ENOMEM); + tmp += s->mb_stride + 1; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + s->p_field_mv_table[i][j] = tmp; + tmp += mv_table_size; } - if (!FF_ALLOCZ_TYPED_ARRAY(s->p_field_select_table[i], mv_table_size * 2)) - return AVERROR(ENOMEM); } } + 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; } @@ -819,13 +652,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) @@ -876,14 +709,14 @@ static void clear_context(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; + s->b_field_mv_table_base = NULL; + s->p_field_mv_table_base = NULL; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - s->b_field_mv_table_base[i][j][k] = NULL; s->b_field_mv_table[i][j][k] = NULL; } s->b_field_select_table[i][j] = NULL; - s->p_field_mv_table_base[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } s->p_field_select_table[i] = NULL; @@ -971,7 +804,7 @@ av_cold int ff_mpv_common_init(MpegEncContext *s) !(s->new_picture.f = 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 @@ -984,7 +817,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; // } @@ -997,13 +830,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; @@ -1022,17 +849,19 @@ static void free_context_frame(MpegEncContext *s) s->b_bidir_forw_mv_table = NULL; s->b_bidir_back_mv_table = NULL; s->b_direct_mv_table = NULL; + av_freep(&s->b_field_mv_table_base); + av_freep(&s->b_field_select_table[0][0]); + av_freep(&s->p_field_mv_table_base); + av_freep(&s->p_field_select_table[0]); for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { - av_freep(&s->b_field_mv_table_base[i][j][k]); s->b_field_mv_table[i][j][k] = NULL; } - av_freep(&s->b_field_select_table[i][j]); - av_freep(&s->p_field_mv_table_base[i][j]); + s->b_field_select_table[i][j] = NULL; s->p_field_mv_table[i][j] = NULL; } - av_freep(&s->p_field_select_table[i]); + s->p_field_select_table[i] = NULL; } av_freep(&s->dc_val_base); @@ -1054,61 +883,6 @@ 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) { @@ -1117,7 +891,7 @@ void ff_mpv_common_end(MpegEncContext *s) if (!s) return; - free_context_frame(s); + ff_mpv_free_context_frame(s); if (s->slice_context_count > 1) s->slice_context_count = 1; @@ -1162,296 +936,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, @@ -1949,27 +1433,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 */ @@ -1986,8 +1453,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; @@ -1995,12 +1462,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) { @@ -2030,7 +1497,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) { @@ -2057,7 +1524,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; @@ -2082,7 +1549,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); @@ -2129,14 +1596,13 @@ 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){ + if (!is_mpeg12 && s->avctx->bits_per_raw_sample > 8) { const int act_block_size = block_size * 2; if(s->dpcm_direction == 0) { @@ -2172,10 +1638,11 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], dest_pcm[i] += linesize[i] / 2; } } - } else if(s->dpcm_direction == -1) { + } else { 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}; + av_assert2(s->dpcm_direction == -1); for(i = 0; i < 3; i++) { int idx = 0; int vsub = i ? s->chroma_y_shift : 0; @@ -2190,7 +1657,7 @@ void mpv_reconstruct_mb_internal(MpegEncContext *s, int16_t block[12][64], } } /* 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); @@ -2251,6 +1718,24 @@ skip_idct: void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]) { + 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 */ + 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); @@ -2261,13 +1746,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]; @@ -2301,36 +1779,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; - s->closed_gop= 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. */ @@ -2347,9 +1795,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 e90669b776..448fe2cedc 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -53,13 +53,11 @@ #include "parser.h" #endif #include "mpegutils.h" -#include "mpeg12data.h" #include "qpeldsp.h" -#include "thread.h" +#include "rl.h" #include "videodsp.h" #include "libavutil/opt.h" -#include "libavutil/timecode.h" #define MAX_THREADS 32 @@ -198,14 +196,12 @@ typedef struct MpegEncContext { int *lambda_table; int adaptive_quant; ///< use adaptive quantization int dquant; ///< qscale difference to prev qscale - int closed_gop; ///< MPEG1/2 GOP is closed int pict_type; ///< AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, ... int vbv_delay; 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 @@ -233,8 +229,8 @@ typedef struct MpegEncContext { int16_t (*b_bidir_forw_mv_table_base)[2]; int16_t (*b_bidir_back_mv_table_base)[2]; int16_t (*b_direct_mv_table_base)[2]; - int16_t (*p_field_mv_table_base[2][2])[2]; - int16_t (*b_field_mv_table_base[2][2][2])[2]; + int16_t (*p_field_mv_table_base)[2]; + int16_t (*b_field_mv_table_base)[2]; int16_t (*p_mv_table)[2]; ///< MV table (1MV per MB) P-frame encoding int16_t (*b_forw_mv_table)[2]; ///< MV table (1MV per MB) forward mode B-frame encoding int16_t (*b_back_mv_table)[2]; ///< MV table (1MV per MB) backward mode B-frame encoding @@ -243,8 +239,8 @@ typedef struct MpegEncContext { int16_t (*b_direct_mv_table)[2]; ///< MV table (1MV per MB) direct mode B-frame encoding int16_t (*p_field_mv_table[2][2])[2]; ///< MV table (2MV per MB) interlaced P-frame encoding int16_t (*b_field_mv_table[2][2][2])[2];///< MV table (4MV per MB) interlaced B-frame encoding - uint8_t (*p_field_select_table[2]); - uint8_t (*b_field_select_table[2][2]); + uint8_t (*p_field_select_table[2]); ///< Only the first element is allocated + uint8_t (*b_field_select_table[2][2]); ///< Only the first element is allocated int motion_est; ///< ME algorithm int me_penalty_compensation; int me_pre; ///< prepass for motion estimation @@ -291,7 +287,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 @@ -347,7 +342,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; @@ -414,8 +408,6 @@ typedef struct MpegEncContext { /* MJPEG specific */ struct MJpegContext *mjpeg_ctx; int esc_pos; - int pred; - int huffman; /* MSMPEG4 specific */ int mv_table_index; @@ -449,7 +441,6 @@ typedef struct MpegEncContext { /* 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; @@ -463,8 +454,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 @@ -484,16 +473,11 @@ 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. @@ -576,6 +560,10 @@ typedef struct MpegEncContext { int noise_reduction; int intra_penalty; + +#if FF_API_MPEGVIDEO_OPTS || FF_API_MJPEG_PRED + int dummy; ///< used as target for deprecated options +#endif } MpegEncContext; /* mpegvideo_enc common options */ @@ -663,9 +651,9 @@ FF_MPV_OPT_CMP_FUNC, \ #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 }, + { "a53cc", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), 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 }, + { "force_duplicated_matrix", "Deprecated, does nothing", FF_MPV_OFFSET(dummy), 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 }, \ @@ -690,10 +678,32 @@ 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); +/** + * 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); void ff_mpv_reconstruct_mb(MpegEncContext *s, int16_t block[12][64]); void ff_mpv_report_decode_progress(MpegEncContext *s); diff --git a/libavcodec/mpegvideo_dec.c b/libavcodec/mpegvideo_dec.c new file mode 100644 index 0000000000..1e238bd1e1 --- /dev/null +++ b/libavcodec/mpegvideo_dec.c @@ -0,0 +1,582 @@ +/* + * 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 "thread.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) { + int err; + memcpy(s, s1, sizeof(*s)); + + 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(*s)); + 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 (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; + // 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 */ + 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_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 f804b8215d..35f0f79d4e 100644 --- a/libavcodec/mpegvideo_enc.c +++ b/libavcodec/mpegvideo_enc.c @@ -45,6 +45,7 @@ #include "encode.h" #include "idctdsp.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "mpegvideo.h" #include "mpegvideodata.h" #include "h261.h" @@ -63,6 +64,7 @@ #include "aandcttab.h" #include "flv.h" #include "mpeg4video.h" +#include "mpeg4videodata.h" #include "internal.h" #include "bytestream.h" #include "wmv2.h" @@ -370,9 +372,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); @@ -573,15 +572,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, @@ -619,24 +609,6 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) 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"); @@ -885,15 +857,16 @@ av_cold int ff_mpv_encode_init(AVCodecContext *avctx) ff_set_cmp(&s->mecc, s->mecc.ildct_cmp, avctx->ildct_cmp); ff_set_cmp(&s->mecc, s->mecc.frame_skip_cmp, s->frame_skip_cmp); - if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) + if (CONFIG_H261_ENCODER && s->out_format == FMT_H261) { ff_h261_encode_init(s); - if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) - ff_h263_encode_init(s); - if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) - ff_msmpeg4_encode_init(s); - if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) - && s->out_format == FMT_MPEG1) + } else if ((CONFIG_MPEG1VIDEO_ENCODER || CONFIG_MPEG2VIDEO_ENCODER) + && s->out_format == FMT_MPEG1) { ff_mpeg1_encode_init(s); + } else if (CONFIG_H263_ENCODER && s->out_format == FMT_H263) { + ff_h263_encode_init(s); + if (CONFIG_MSMPEG4_ENCODER && s->msmpeg4_version) + ff_msmpeg4_encode_init(s); + } /* init q matrix */ for (i = 0; i < 64; i++) { @@ -969,9 +942,6 @@ 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]); @@ -1658,8 +1628,7 @@ static int frame_start(MpegEncContext *s) 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; + s->next_picture_ptr = s->current_picture_ptr; } if (s->last_picture_ptr) { @@ -1823,7 +1792,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) @@ -2062,8 +2031,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; @@ -2119,8 +2095,8 @@ static av_always_inline void encode_mb_internal(MpegEncContext *s, 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 +2117,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 +2136,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 +2154,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 +2196,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 +2221,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 +2240,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 +2265,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 +2291,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 +2349,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,9 +2421,12 @@ 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){ @@ -2938,8 +2917,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 +2933,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; } @@ -3436,8 +3415,6 @@ static void merge_context_after_encode(MpegEncContext *dst, MpegEncContext *src) 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]); @@ -3521,7 +3498,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) /* we need to initialize some time vars before we can encode B-frames */ // RAL: Condition added for MPEG1VIDEO - if (s->codec_id == AV_CODEC_ID_MPEG1VIDEO || s->codec_id == AV_CODEC_ID_MPEG2VIDEO || (s->h263_pred && !s->msmpeg4_version)) + if (s->out_format == FMT_MPEG1 || (s->h263_pred && !s->msmpeg4_version)) set_frame_distances(s); if(CONFIG_MPEG4_ENCODER && s->codec_id == AV_CODEC_ID_MPEG4) ff_set_mpeg4_time(s); @@ -3550,7 +3527,7 @@ static int encode_picture(MpegEncContext *s, int picture_number) update_qscale(s); } - if(s->codec_id != AV_CODEC_ID_AMV && s->codec_id != AV_CODEC_ID_MJPEG){ + if (s->out_format != FMT_MJPEG) { 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); s->q_chroma_intra_matrix = s->q_intra_matrix; @@ -3628,9 +3605,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); @@ -3696,28 +3671,27 @@ static int encode_picture(MpegEncContext *s, int picture_number) ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); s->qscale= 8; - } - if(s->codec_id == AV_CODEC_ID_AMV){ - static const uint8_t y[32]={13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; - static const uint8_t c[32]={14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; - for(i=1;i<64;i++){ - int j= s->idsp.idct_permutation[ff_zigzag_direct[i]]; - s->intra_matrix[j] = sp5x_qscale_five_quant_table[0][i]; - s->chroma_intra_matrix[j] = sp5x_qscale_five_quant_table[1][i]; + if (s->codec_id == AV_CODEC_ID_AMV) { + static const uint8_t y[32] = {13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13}; + static const uint8_t c[32] = {14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14}; + for (int i = 1; i < 64; i++) { + int j = s->idsp.idct_permutation[ff_zigzag_direct[i]]; + + s->intra_matrix[j] = sp5x_qscale_five_quant_table[0][i]; + s->chroma_intra_matrix[j] = sp5x_qscale_five_quant_table[1][i]; + } + s->y_dc_scale_table = y; + s->c_dc_scale_table = c; + s->intra_matrix[0] = 13; + s->chroma_intra_matrix[0] = 14; + ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, + s->intra_matrix, s->intra_quant_bias, 8, 8, 1); + ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, + s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); + s->qscale = 8; } - s->y_dc_scale_table= y; - s->c_dc_scale_table= c; - s->intra_matrix[0] = 13; - s->chroma_intra_matrix[0] = 14; - ff_convert_matrix(s, s->q_intra_matrix, s->q_intra_matrix16, - s->intra_matrix, s->intra_quant_bias, 8, 8, 1); - ff_convert_matrix(s, s->q_chroma_intra_matrix, s->q_chroma_intra_matrix16, - s->chroma_intra_matrix, s->intra_quant_bias, 8, 8, 1); - s->qscale= 8; - } - - if (s->out_format == FMT_SPEEDHQ) { + } else if (s->out_format == FMT_SPEEDHQ) { s->y_dc_scale_table= s->c_dc_scale_table= ff_mpeg2_dc_scale_table[3]; } @@ -3736,10 +3710,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: diff --git a/libavcodec/mpegvideo_motion.c b/libavcodec/mpegvideo_motion.c index 427bc96887..876a7375f8 100644 --- a/libavcodec/mpegvideo_motion.c +++ b/libavcodec/mpegvideo_motion.c @@ -839,8 +839,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 +976,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 39b9f2e43a..c5dc867d24 100644 --- a/libavcodec/mpegvideo_parser.c +++ b/libavcodec/mpegvideo_parser.c @@ -22,6 +22,7 @@ #include "parser.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "internal.h" struct MpvParseContext { diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index 16b6f18950..f12586dd64 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -34,8 +34,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/msmpeg4data.c b/libavcodec/msmpeg4data.c index 890aeb5670..63f30ac544 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/mss4.c b/libavcodec/mss4.c index 6c44c76c50..216df2852d 100644 --- a/libavcodec/mss4.c +++ b/libavcodec/mss4.c @@ -124,10 +124,10 @@ static av_cold void mss4_init_vlcs(void) for (unsigned i = 0, offset = 0; i < 2; i++) { mss4_init_vlc(&dc_vlc[i], &offset, mss4_dc_vlc_lens[i], NULL); mss4_init_vlc(&ac_vlc[i], &offset, - i ? avpriv_mjpeg_bits_ac_chrominance + 1 - : avpriv_mjpeg_bits_ac_luminance + 1, - i ? avpriv_mjpeg_val_ac_chrominance - : avpriv_mjpeg_val_ac_luminance); + i ? ff_mjpeg_bits_ac_chrominance + 1 + : ff_mjpeg_bits_ac_luminance + 1, + i ? ff_mjpeg_val_ac_chrominance + : ff_mjpeg_val_ac_luminance); mss4_init_vlc(&vec_entry_vlc[i], &offset, mss4_vec_entry_vlc_lens[i], mss4_vec_entry_vlc_syms[i]); } diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c index edc46ed33a..850c46022b 100644 --- a/libavcodec/nvenc.c +++ b/libavcodec/nvenc.c @@ -1856,7 +1856,7 @@ static int nvenc_register_frame(AVCodecContext *avctx, const AVFrame *frame) NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs; AVHWFramesContext *frames_ctx = (AVHWFramesContext*)frame->hw_frames_ctx->data; - NV_ENC_REGISTER_RESOURCE reg; + NV_ENC_REGISTER_RESOURCE reg = { 0 }; int i, idx, ret; for (i = 0; i < ctx->nb_registered_frames; i++) { @@ -2217,6 +2217,9 @@ static int prepare_sei_data_array(AVCodecContext *avctx, const AVFrame *frame) } } + if (!ctx->udu_sei) + return sei_count; + for (i = 0; i < frame->nb_side_data; i++) { AVFrameSideData *side_data = frame->side_data[i]; void *tmp; diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h index 08531e1be3..b42a156c56 100644 --- a/libavcodec/nvenc.h +++ b/libavcodec/nvenc.h @@ -235,6 +235,7 @@ typedef struct NvencContext int intra_refresh; int single_slice_intra_refresh; int constrained_encoding; + int udu_sei; } NvencContext; int ff_nvenc_encode_init(AVCodecContext *avctx); diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c index 7d78aa0d87..89e9a043fc 100644 --- a/libavcodec/nvenc_h264.c +++ b/libavcodec/nvenc_h264.c @@ -188,6 +188,8 @@ static const AVOption options[] = { #endif { "extra_sei", "Pass on extra SEI data (e.g. a53 cc) to be included in the bitstream", OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "udu_sei", "Pass on user data unregistered SEI if available", + OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "intra-refresh","Use Periodic Intra Refresh instead of IDR frames", OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "single-slice-intra-refresh", "Use single slice intra refresh", diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c index a13ac5a395..c2c13bb210 100644 --- a/libavcodec/nvenc_hevc.c +++ b/libavcodec/nvenc_hevc.c @@ -169,6 +169,8 @@ static const AVOption options[] = { #endif { "extra_sei", "Pass on extra SEI data (e.g. a53 cc) to be included in the bitstream", OFFSET(extra_sei), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VE }, + { "udu_sei", "Pass on user data unregistered SEI if available", + OFFSET(udu_sei), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "intra-refresh","Use Periodic Intra Refresh instead of IDR frames", OFFSET(intra_refresh),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "single-slice-intra-refresh", "Use single slice intra refresh", diff --git a/libavcodec/packet.h b/libavcodec/packet.h index 9baff24635..4a349fe051 100644 --- a/libavcodec/packet.h +++ b/libavcodec/packet.h @@ -410,6 +410,9 @@ typedef struct AVPacket { /** * Time base of the packet's timestamps. + * In the future, this field may be set on packets output by encoders or + * demuxers, but its value will be by default ignored on input to decoders + * or muxers. */ AVRational time_base; } AVPacket; diff --git a/libavcodec/packet_internal.h b/libavcodec/packet_internal.h index a10931c106..92a0d4e6d5 100644 --- a/libavcodec/packet_internal.h +++ b/libavcodec/packet_internal.h @@ -23,16 +23,19 @@ #include "packet.h" -typedef struct PacketList { - struct PacketList *next; +typedef struct PacketListEntry { + struct PacketListEntry *next; AVPacket pkt; +} PacketListEntry; + +typedef struct PacketList { + PacketListEntry *head, *tail; } PacketList; /** * Append an AVPacket to the list. * - * @param head List head element - * @param tail List tail element + * @param list A PacketList * @param pkt The packet being appended. The data described in it will * be made reference counted if it isn't already. * @param copy A callback to copy the contents of the packet to the list. @@ -41,8 +44,7 @@ typedef struct PacketList { * @return 0 on success, negative AVERROR value on failure. On failure, the packet and the list are unchanged. */ -int avpriv_packet_list_put(PacketList **head, PacketList **tail, - AVPacket *pkt, +int avpriv_packet_list_put(PacketList *list, AVPacket *pkt, int (*copy)(AVPacket *dst, const AVPacket *src), int flags); @@ -52,22 +54,17 @@ int avpriv_packet_list_put(PacketList **head, PacketList **tail, * @note The pkt will be overwritten completely on success. The caller * owns the packet and must unref it by itself. * - * @param head List head element - * @param tail List tail element + * @param head A pointer to a PacketList struct * @param pkt Pointer to an AVPacket struct * @return 0 on success, and a packet is returned. AVERROR(EAGAIN) if * the list was empty. */ -int avpriv_packet_list_get(PacketList **head, PacketList **tail, - AVPacket *pkt); +int avpriv_packet_list_get(PacketList *list, AVPacket *pkt); /** * Wipe the list and unref all the packets in it. - * - * @param head List head element - * @param tail List tail element */ -void avpriv_packet_list_free(PacketList **head, PacketList **tail); +void avpriv_packet_list_free(PacketList *list); int ff_side_data_set_encoder_stats(AVPacket *pkt, int quality, int64_t *error, int error_count, int pict_type); diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index 388639a110..bdd20c914b 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -443,6 +443,7 @@ static int parse_presentation_segment(AVCodecContext *avctx, for (i = 0; i < ctx->presentation.object_count; i++) { + PGSSubObjectRef *const object = &ctx->presentation.objects[i]; if (buf_end - buf < 8) { av_log(avctx, AV_LOG_ERROR, "Insufficent space for object\n"); @@ -450,32 +451,29 @@ static int parse_presentation_segment(AVCodecContext *avctx, return AVERROR_INVALIDDATA; } - ctx->presentation.objects[i].id = bytestream_get_be16(&buf); - ctx->presentation.objects[i].window_id = bytestream_get_byte(&buf); - ctx->presentation.objects[i].composition_flag = bytestream_get_byte(&buf); + object->id = bytestream_get_be16(&buf); + object->window_id = bytestream_get_byte(&buf); + object->composition_flag = bytestream_get_byte(&buf); - ctx->presentation.objects[i].x = bytestream_get_be16(&buf); - ctx->presentation.objects[i].y = bytestream_get_be16(&buf); + object->x = bytestream_get_be16(&buf); + object->y = bytestream_get_be16(&buf); // If cropping - if (ctx->presentation.objects[i].composition_flag & 0x80) { - ctx->presentation.objects[i].crop_x = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_y = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_w = bytestream_get_be16(&buf); - ctx->presentation.objects[i].crop_h = bytestream_get_be16(&buf); + if (object->composition_flag & 0x80) { + object->crop_x = bytestream_get_be16(&buf); + object->crop_y = bytestream_get_be16(&buf); + object->crop_w = bytestream_get_be16(&buf); + object->crop_h = bytestream_get_be16(&buf); } ff_dlog(avctx, "Subtitle Placement x=%d, y=%d\n", - ctx->presentation.objects[i].x, ctx->presentation.objects[i].y); + object->x, object->y); - if (ctx->presentation.objects[i].x > avctx->width || - ctx->presentation.objects[i].y > avctx->height) { + if (object->x > avctx->width || object->y > avctx->height) { av_log(avctx, AV_LOG_ERROR, "Subtitle out of video bounds. x = %d, y = %d, video width = %d, video height = %d.\n", - ctx->presentation.objects[i].x, - ctx->presentation.objects[i].y, + object->x, object->y, avctx->width, avctx->height); - ctx->presentation.objects[i].x = 0; - ctx->presentation.objects[i].y = 0; + object->y = object->x = 0; if (avctx->err_recognition & AV_EF_EXPLODE) { return AVERROR_INVALIDDATA; } @@ -531,15 +529,13 @@ static int display_end_segment(AVCodecContext *avctx, void *data, return AVERROR_INVALIDDATA; } for (i = 0; i < ctx->presentation.object_count; i++) { + AVSubtitleRect *const rect = av_mallocz(sizeof(*rect)); PGSSubObject *object; - sub->rects[i] = av_mallocz(sizeof(*sub->rects[0])); - if (!sub->rects[i]) { - avsubtitle_free(sub); + if (!rect) return AVERROR(ENOMEM); - } - sub->num_rects++; - sub->rects[i]->type = SUBTITLE_BITMAP; + sub->rects[sub->num_rects++] = rect; + rect->type = SUBTITLE_BITMAP; /* Process bitmap */ object = find_object(ctx->presentation.objects[i].id, &ctx->objects); @@ -547,55 +543,48 @@ static int display_end_segment(AVCodecContext *avctx, void *data, // Missing object. Should only happen with damaged streams. av_log(avctx, AV_LOG_ERROR, "Invalid object id %d\n", ctx->presentation.objects[i].id); - if (avctx->err_recognition & AV_EF_EXPLODE) { - avsubtitle_free(sub); + if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; - } // Leaves rect empty with 0 width and height. continue; } if (ctx->presentation.objects[i].composition_flag & 0x40) - sub->rects[i]->flags |= AV_SUBTITLE_FLAG_FORCED; + rect->flags |= AV_SUBTITLE_FLAG_FORCED; - sub->rects[i]->x = ctx->presentation.objects[i].x; - sub->rects[i]->y = ctx->presentation.objects[i].y; + rect->x = ctx->presentation.objects[i].x; + rect->y = ctx->presentation.objects[i].y; if (object->rle) { - sub->rects[i]->w = object->w; - sub->rects[i]->h = object->h; + rect->w = object->w; + rect->h = object->h; - sub->rects[i]->linesize[0] = object->w; + rect->linesize[0] = object->w; if (object->rle_remaining_len) { av_log(avctx, AV_LOG_ERROR, "RLE data length %u is %u bytes shorter than expected\n", object->rle_data_len, object->rle_remaining_len); - if (avctx->err_recognition & AV_EF_EXPLODE) { - avsubtitle_free(sub); + if (avctx->err_recognition & AV_EF_EXPLODE) return AVERROR_INVALIDDATA; - } } - ret = decode_rle(avctx, sub->rects[i], object->rle, object->rle_data_len); + ret = decode_rle(avctx, rect, object->rle, object->rle_data_len); if (ret < 0) { if ((avctx->err_recognition & AV_EF_EXPLODE) || ret == AVERROR(ENOMEM)) { - avsubtitle_free(sub); return ret; } - sub->rects[i]->w = 0; - sub->rects[i]->h = 0; + rect->w = 0; + rect->h = 0; continue; } } /* Allocate memory for colors */ - sub->rects[i]->nb_colors = 256; - sub->rects[i]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[i]->data[1]) { - avsubtitle_free(sub); + rect->nb_colors = 256; + rect->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!rect->data[1]) return AVERROR(ENOMEM); - } if (!ctx->forced_subs_only || ctx->presentation.objects[i].composition_flag & 0x40) - memcpy(sub->rects[i]->data[1], palette->clut, sub->rects[i]->nb_colors * sizeof(uint32_t)); + memcpy(rect->data[1], palette->clut, rect->nb_colors * sizeof(uint32_t)); } return 1; } @@ -677,11 +666,9 @@ static int decode(AVCodecContext *avctx, void *data, int *got_sub_ptr, ret = AVERROR_INVALIDDATA; break; } - if (ret < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) { - avsubtitle_free(data); - *got_sub_ptr = 0; + if (ret < 0 && (ret == AVERROR(ENOMEM) || + avctx->err_recognition & AV_EF_EXPLODE)) return ret; - } buf += segment_length; } diff --git a/libavcodec/proresdec.h b/libavcodec/proresdec.h index 06e41dd09a..1e48752e6f 100644 --- a/libavcodec/proresdec.h +++ b/libavcodec/proresdec.h @@ -52,6 +52,7 @@ typedef struct { int first_field; int alpha_info; void (*unpack_alpha)(GetBitContext *gb, uint16_t *dst, int num_coeffs, const int num_bits); + enum AVPixelFormat pix_fmt; } ProresContext; #endif /* AVCODEC_PRORESDEC_H */ diff --git a/libavcodec/proresdec2.c b/libavcodec/proresdec2.c index 7750620b22..d2d881a3dd 100644 --- a/libavcodec/proresdec2.c +++ b/libavcodec/proresdec2.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "get_bits.h" +#include "hwconfig.h" #include "idctdsp.h" #include "internal.h" #include "profiles.h" @@ -187,6 +188,8 @@ static av_cold int decode_init(AVCodecContext *avctx) permute(ctx->progressive_scan, ff_prores_progressive_scan, idct_permutation); permute(ctx->interlaced_scan, ff_prores_interlaced_scan, idct_permutation); + ctx->pix_fmt = AV_PIX_FMT_NONE; + if (avctx->bits_per_raw_sample == 10){ ctx->unpack_alpha = unpack_alpha_10; } else if (avctx->bits_per_raw_sample == 12){ @@ -204,6 +207,7 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, int hdr_size, width, height, flags; int version; const uint8_t *ptr; + enum AVPixelFormat pix_fmt; hdr_size = AV_RB16(buf); ff_dlog(avctx, "header size %d\n", hdr_size); @@ -252,18 +256,37 @@ static int decode_frame_header(ProresContext *ctx, const uint8_t *buf, if (ctx->alpha_info) { if (avctx->bits_per_raw_sample == 10) { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P10 : AV_PIX_FMT_YUVA422P10; } else { /* 12b */ - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUVA444P12 : AV_PIX_FMT_YUVA422P12; } } else { if (avctx->bits_per_raw_sample == 10) { - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P10 : AV_PIX_FMT_YUV422P10; } else { /* 12b */ - avctx->pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12; + pix_fmt = (buf[12] & 0xC0) == 0xC0 ? AV_PIX_FMT_YUV444P12 : AV_PIX_FMT_YUV422P12; } } + if (pix_fmt != ctx->pix_fmt) { +#define HWACCEL_MAX (CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL) + enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; + int ret; + + ctx->pix_fmt = pix_fmt; + +#if CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL + *fmtp++ = AV_PIX_FMT_VIDEOTOOLBOX; +#endif + *fmtp++ = ctx->pix_fmt; + *fmtp = AV_PIX_FMT_NONE; + + if ((ret = ff_thread_get_format(avctx, pix_fmts)) < 0) + return ret; + + avctx->pix_fmt = ret; + } + avctx->color_primaries = buf[14]; avctx->color_trc = buf[15]; avctx->colorspace = buf[16]; @@ -782,6 +805,23 @@ 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) + return ret; + ff_thread_finish_setup(avctx); + + if (avctx->hwaccel) { + ret = avctx->hwaccel->start_frame(avctx, NULL, 0); + if (ret < 0) + return ret; + ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size); + if (ret < 0) + return ret; + ret = avctx->hwaccel->end_frame(avctx); + if (ret < 0) + return ret; + goto finish; + } + decode_picture: pic_size = decode_picture_header(avctx, buf, buf_size); if (pic_size < 0) { @@ -789,10 +829,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return pic_size; } - if (ctx->first_field) - if ((ret = ff_thread_get_buffer(avctx, &tframe, 0)) < 0) - return ret; - if ((ret = decode_picture(avctx)) < 0) { av_log(avctx, AV_LOG_ERROR, "error decoding picture\n"); return ret; @@ -806,6 +842,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, goto decode_picture; } +finish: *got_frame = 1; return avpkt->size; @@ -820,6 +857,18 @@ static av_cold int decode_close(AVCodecContext *avctx) return 0; } +#if HAVE_THREADS +static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) +{ + ProresContext *csrc = src->priv_data; + ProresContext *cdst = dst->priv_data; + + cdst->pix_fmt = csrc->pix_fmt; + + return 0; +} +#endif + const AVCodec ff_prores_decoder = { .name = "prores", .long_name = NULL_IF_CONFIG_SMALL("Apple ProRes (iCodec Pro)"), @@ -829,7 +878,14 @@ const AVCodec ff_prores_decoder = { .init = decode_init, .close = decode_close, .decode = 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), .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, + .hw_configs = (const AVCodecHWConfigInternal *const []) { +#if CONFIG_PRORES_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(prores), +#endif + NULL + }, }; diff --git a/libavcodec/pthread_frame.c b/libavcodec/pthread_frame.c index 73b1b7d7d9..85a6bc98c1 100644 --- a/libavcodec/pthread_frame.c +++ b/libavcodec/pthread_frame.c @@ -765,14 +765,14 @@ 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, - AVCodecContext *src, const AVCodec *codec, int first) + const AVCodec *codec, int first) { AVCodecContext *copy; int err; atomic_init(&p->state, STATE_INPUT_READY); - copy = av_memdup(src, sizeof(*src)); + copy = av_memdup(avctx, sizeof(*avctx)); if (!copy) return AVERROR(ENOMEM); copy->priv_data = NULL; @@ -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(src->internal, sizeof(*src->internal)); + copy->internal = av_memdup(avctx->internal, sizeof(*avctx->internal)); if (!copy->internal) return AVERROR(ENOMEM); copy->internal->thread_ctx = p; @@ -798,7 +798,7 @@ static av_cold int init_thread(PerThreadContext *p, int *threads_to_free, if (codec->priv_class) { *(const AVClass **)copy->priv_data = codec->priv_class; - err = av_opt_copy(copy->priv_data, src->priv_data); + err = av_opt_copy(copy->priv_data, avctx->priv_data); if (err < 0) return err; } @@ -843,7 +843,6 @@ int ff_frame_thread_init(AVCodecContext *avctx) { int thread_count = avctx->thread_count; const AVCodec *codec = avctx->codec; - AVCodecContext *src = avctx; FrameThreadContext *fctx; int err, i = 0; @@ -876,7 +875,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) fctx->delaying = 1; if (codec->type == AVMEDIA_TYPE_VIDEO) - avctx->delay = src->thread_count - 1; + avctx->delay = avctx->thread_count - 1; fctx->threads = av_calloc(thread_count, sizeof(*fctx->threads)); if (!fctx->threads) { @@ -888,7 +887,7 @@ int ff_frame_thread_init(AVCodecContext *avctx) PerThreadContext *p = &fctx->threads[i]; int first = !i; - err = init_thread(p, &i, fctx, avctx, src, codec, first); + err = init_thread(p, &i, fctx, avctx, codec, first); if (err < 0) goto error; } diff --git a/libavcodec/put_golomb.h b/libavcodec/put_golomb.h new file mode 100644 index 0000000000..9ca911fc3c --- /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/qsv_internal.h b/libavcodec/qsv_internal.h index 8090b748b3..fe9d5319c4 100644 --- a/libavcodec/qsv_internal.h +++ b/libavcodec/qsv_internal.h @@ -76,6 +76,8 @@ typedef struct QSVFrame { mfxExtDecodedFrameInfo dec_info; mfxExtBuffer *ext_param; + mfxPayload *payloads[QSV_MAX_ENC_PAYLOAD]; ///< used for enc_ctrl.Payload + int queued; int used; diff --git a/libavcodec/qsvdec.c b/libavcodec/qsvdec.c index 8bce9f2cf0..d9e0fef1f1 100644 --- a/libavcodec/qsvdec.c +++ b/libavcodec/qsvdec.c @@ -570,7 +570,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, return AVERROR_BUG; } - out_frame->queued = 1; + 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); } else { @@ -583,7 +583,7 @@ static int qsv_decode(AVCodecContext *avctx, QSVContext *q, 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; + out_frame->queued -= 1; if (avctx->pix_fmt != AV_PIX_FMT_QSV) { do { @@ -754,8 +754,6 @@ 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); diff --git a/libavcodec/qsvenc.c b/libavcodec/qsvenc.c index 06f55604b5..4e7a15f060 100644 --- a/libavcodec/qsvenc.c +++ b/libavcodec/qsvenc.c @@ -41,42 +41,84 @@ #include "qsv_internal.h" #include "qsvenc.h" -static const struct { +struct profile_names { mfxU16 profile; const char *name; -} profile_names[] = { - { MFX_PROFILE_AVC_BASELINE, "baseline" }, - { MFX_PROFILE_AVC_MAIN, "main" }, - { MFX_PROFILE_AVC_EXTENDED, "extended" }, - { MFX_PROFILE_AVC_HIGH, "high" }, +}; + +static const struct profile_names avc_profiles[] = { + { MFX_PROFILE_AVC_BASELINE, "avc baseline" }, + { 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, "high 422" }, + { MFX_PROFILE_AVC_HIGH_422, "avc high 422" }, #endif #if QSV_VERSION_ATLEAST(1, 4) - { MFX_PROFILE_AVC_CONSTRAINED_BASELINE, "constrained baseline" }, - { MFX_PROFILE_AVC_CONSTRAINED_HIGH, "constrained high" }, - { MFX_PROFILE_AVC_PROGRESSIVE_HIGH, "progressive high" }, -#endif - { MFX_PROFILE_MPEG2_SIMPLE, "simple" }, - { MFX_PROFILE_MPEG2_MAIN, "main" }, - { MFX_PROFILE_MPEG2_HIGH, "high" }, - { MFX_PROFILE_VC1_SIMPLE, "simple" }, - { MFX_PROFILE_VC1_MAIN, "main" }, - { MFX_PROFILE_VC1_ADVANCED, "advanced" }, -#if QSV_VERSION_ATLEAST(1, 8) - { MFX_PROFILE_HEVC_MAIN, "main" }, - { MFX_PROFILE_HEVC_MAIN10, "main10" }, - { MFX_PROFILE_HEVC_MAINSP, "mainsp" }, - { MFX_PROFILE_HEVC_REXT, "rext" }, + { 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 char *print_profile(mfxU16 profile) +static const struct profile_names mpeg2_profiles[] = { + { MFX_PROFILE_MPEG2_SIMPLE, "mpeg2 simple" }, + { MFX_PROFILE_MPEG2_MAIN, "mpeg2 main" }, + { MFX_PROFILE_MPEG2_HIGH, "mpeg2 high" }, +}; + +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" }, +#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 +}; + +static const char *print_profile(enum AVCodecID codec_id, mfxU16 profile) { - int i; - for (i = 0; i < FF_ARRAY_ELEMS(profile_names); i++) - if (profile == profile_names[i].profile) - return profile_names[i].name; + const struct profile_names *profiles; + int i, num_profiles; + + switch (codec_id) { + case AV_CODEC_ID_H264: + profiles = avc_profiles; + num_profiles = FF_ARRAY_ELEMS(avc_profiles); + break; + + case AV_CODEC_ID_MPEG2VIDEO: + profiles = mpeg2_profiles; + num_profiles = FF_ARRAY_ELEMS(mpeg2_profiles); + break; + + case AV_CODEC_ID_HEVC: + profiles = hevc_profiles; + num_profiles = FF_ARRAY_ELEMS(hevc_profiles); + break; + + case AV_CODEC_ID_VP9: + profiles = vp9_profiles; + num_profiles = FF_ARRAY_ELEMS(vp9_profiles); + break; + + default: + return "unknown"; + } + + for (i = 0; i < num_profiles; i++) + if (profile == profiles[i].profile) + return profiles[i].name; + return "unknown"; } @@ -146,7 +188,7 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, #endif av_log(avctx, AV_LOG_VERBOSE, "profile: %s; level: %"PRIu16"\n", - print_profile(info->CodecProfile), info->CodecLevel); + print_profile(avctx->codec_id, info->CodecProfile), info->CodecLevel); av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", info->GopPicSize, info->GopRefDist); @@ -168,6 +210,11 @@ 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); @@ -301,6 +348,96 @@ static void dump_video_param(AVCodecContext *avctx, QSVEncContext *q, } +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 + + av_log(avctx, AV_LOG_VERBOSE, "profile: %s \n", + print_profile(avctx->codec_id, info->CodecProfile)); + + av_log(avctx, AV_LOG_VERBOSE, "GopPicSize: %"PRIu16"; GopRefDist: %"PRIu16"; GopOptFlag: ", + info->GopPicSize, info->GopRefDist); + if (info->GopOptFlag & MFX_GOP_CLOSED) + av_log(avctx, AV_LOG_VERBOSE, "closed "); + if (info->GopOptFlag & MFX_GOP_STRICT) + av_log(avctx, AV_LOG_VERBOSE, "strict "); + av_log(avctx, AV_LOG_VERBOSE, "; IdrInterval: %"PRIu16"\n", info->IdrInterval); + + av_log(avctx, AV_LOG_VERBOSE, "TargetUsage: %"PRIu16"; RateControlMethod: %s\n", + info->TargetUsage, print_ratecontrol(info->RateControlMethod)); + + if (info->RateControlMethod == MFX_RATECONTROL_CBR || + info->RateControlMethod == MFX_RATECONTROL_VBR) { + 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); + } 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); + } +#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 +} + +static void dump_video_mjpeg_param(AVCodecContext *avctx, QSVEncContext *q) +{ + mfxInfoMFX *info = &q->param.mfx; + + av_log(avctx, AV_LOG_VERBOSE, "Interleaved: %"PRIu16" \n", info->Interleaved); + av_log(avctx, AV_LOG_VERBOSE, "Quality: %"PRIu16" \n", info->Quality); + av_log(avctx, AV_LOG_VERBOSE, "RestartInterval: %"PRIu16" \n", info->RestartInterval); + + av_log(avctx, AV_LOG_VERBOSE, "FrameRateExtD: %"PRIu32"; FrameRateExtN: %"PRIu32" \n", + info->FrameInfo.FrameRateExtD, info->FrameInfo.FrameRateExtN); +} + static int select_rc_mode(AVCodecContext *avctx, QSVEncContext *q) { const char *rc_desc; @@ -441,7 +578,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; @@ -544,7 +683,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; @@ -610,6 +751,11 @@ 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 @@ -850,6 +996,8 @@ static int qsv_retrieve_enc_jpeg_params(AVCodecContext *avctx, QSVEncContext *q) if (q->packet_size == 0) q->packet_size = q->param.mfx.FrameInfo.Height * q->param.mfx.FrameInfo.Width * 4; + dump_video_mjpeg_param(avctx, q); + return 0; } @@ -899,6 +1047,8 @@ static int qsv_retrieve_enc_vp9_params(AVCodecContext *avctx, QSVEncContext *q) q->packet_size = q->param.mfx.BufferSizeInKB * q->param.mfx.BRCParamMultiplier * 1000; + dump_video_vp9_param(avctx, q, ext_buffers); + return 0; } @@ -1259,7 +1409,7 @@ static void free_encoder_ctrl_payloads(mfxEncodeCtrl* enc_ctrl) if (enc_ctrl) { int i; for (i = 0; i < enc_ctrl->NumPayload && i < QSV_MAX_ENC_PAYLOAD; i++) { - av_free(enc_ctrl->Payload[i]); + av_freep(&enc_ctrl->Payload[i]); } enc_ctrl->NumPayload = 0; } @@ -1273,6 +1423,7 @@ static void clear_unused_frames(QSVEncContext *q) free_encoder_ctrl_payloads(&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; if (cur->frame->format == AV_PIX_FMT_QSV) { av_frame_unref(cur->frame); } @@ -1309,11 +1460,7 @@ static int get_free_frame(QSVEncContext *q, QSVFrame **f) av_freep(&frame); return AVERROR(ENOMEM); } - frame->enc_ctrl.Payload = av_mallocz(sizeof(mfxPayload*) * QSV_MAX_ENC_PAYLOAD); - if (!frame->enc_ctrl.Payload) { - av_freep(&frame); - return AVERROR(ENOMEM); - } + frame->enc_ctrl.Payload = frame->payloads; *last = frame; *f = frame; @@ -1392,8 +1539,23 @@ static int submit_frame(QSVEncContext *q, const AVFrame *frame, qf->surface.Data.PitchLow = qf->frame->linesize[0]; qf->surface.Data.Y = qf->frame->data[0]; qf->surface.Data.UV = qf->frame->data[1]; - } + /* The SDK checks Data.V when using system memory for VP9 encoding */ + switch (frame->format) { + case AV_PIX_FMT_NV12: + qf->surface.Data.V = qf->surface.Data.UV + 1; + break; + + case AV_PIX_FMT_P010: + qf->surface.Data.V = qf->surface.Data.UV + 2; + break; + + default: + /* should not reach here */ + av_assert0(0); + break; + } + } qf->surface.Data.TimeStamp = av_rescale_q(frame->pts, q->avctx->time_base, (AVRational){1, 90000}); *new_frame = qf; @@ -1615,7 +1777,7 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) while (cur) { q->work_frames = cur->next; av_frame_free(&cur->frame); - av_free(cur->enc_ctrl.Payload); + free_encoder_ctrl_payloads(&cur->enc_ctrl); av_freep(&cur); cur = q->work_frames; } @@ -1629,6 +1791,14 @@ int ff_qsv_enc_close(AVCodecContext *avctx, QSVEncContext *q) 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); + } +#endif av_freep(&sync); av_freep(&bs); av_packet_unref(&pkt); diff --git a/libavcodec/qsvenc_h264.c b/libavcodec/qsvenc_h264.c index 80fe3cc280..9f127607b7 100644 --- a/libavcodec/qsvenc_h264.c +++ b/libavcodec/qsvenc_h264.c @@ -103,17 +103,17 @@ static av_cold int qsv_enc_close(AVCodecContext *avctx) static const AVOption options[] = { QSV_COMMON_OPTS - { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "cavlc", "Enable CAVLC", OFFSET(qsv.cavlc), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #if QSV_HAVE_VCM - { "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, + { "vcm", "Use the video conferencing mode ratecontrol", OFFSET(qsv.vcm), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, #endif { "idr_interval", "Distance (in I-frames) between IDR frames", OFFSET(qsv.idr_interval), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, - { "pic_timing_sei", "Insert picture timing SEI with pic_struct_syntax element", OFFSET(qsv.pic_timing_sei), AV_OPT_TYPE_INT, { .i64 = 1 }, 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 }, { "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_INT, { .i64 = 0 }, 0, 1, VE }, + { "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 @@ -139,9 +139,9 @@ static const AVOption options[] = { { "main" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "high" , NULL, 0, AV_OPT_TYPE_CONST, { .i64 = MFX_PROFILE_AVC_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, - { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, VE}, + { "a53cc" , "Use A53 Closed Captions (if available)", OFFSET(qsv.a53_cc), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, VE}, - { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, + { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, #if QSV_HAVE_MF { "mfmode", "Multi-Frame Mode", OFFSET(qsv.mfmode), AV_OPT_TYPE_INT, { .i64 = MFX_MF_AUTO }, MFX_MF_DEFAULT, MFX_MF_AUTO, VE, "mfmode"}, diff --git a/libavcodec/qsvenc_hevc.c b/libavcodec/qsvenc_hevc.c index b7b2f5633e..08aba3011d 100644 --- a/libavcodec/qsvenc_hevc.c +++ b/libavcodec/qsvenc_hevc.c @@ -235,6 +235,9 @@ 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" }, @@ -247,7 +250,7 @@ static const AVOption options[] = { { "tile_cols", "Number of columns for tiled encoding", OFFSET(qsv.tile_cols), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, UINT16_MAX, VE }, { "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_INT, { .i64 = 0 }, 0, 1, VE}, + { "aud", "Insert the Access Unit Delimiter NAL", OFFSET(qsv.aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE}, { NULL }, }; diff --git a/libavcodec/raw.c b/libavcodec/raw.c index 079d5c5d10..5efc1eb465 100644 --- a/libavcodec/raw.c +++ b/libavcodec/raw.c @@ -28,7 +28,7 @@ #include "raw.h" #include "libavutil/common.h" -const PixelFormatTag ff_raw_pix_fmt_tags[] = { +static const PixelFormatTag raw_pix_fmt_tags[] = { { AV_PIX_FMT_YUV420P, MKTAG('I', '4', '2', '0') }, /* Planar formats */ { AV_PIX_FMT_YUV420P, MKTAG('I', 'Y', 'U', 'V') }, { AV_PIX_FMT_YUV420P, MKTAG('y', 'v', '1', '2') }, @@ -299,12 +299,12 @@ const PixelFormatTag ff_raw_pix_fmt_tags[] = { const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void) { - return ff_raw_pix_fmt_tags; + return raw_pix_fmt_tags; } unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) { - const PixelFormatTag *tags = ff_raw_pix_fmt_tags; + const PixelFormatTag *tags = raw_pix_fmt_tags; while (tags->pix_fmt >= 0) { if (tags->pix_fmt == fmt) return tags->fourcc; @@ -313,7 +313,7 @@ unsigned int avcodec_pix_fmt_to_codec_tag(enum AVPixelFormat fmt) return 0; } -const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { +static const PixelFormatTag pix_fmt_bps_avi[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -326,7 +326,7 @@ const PixelFormatTag avpriv_pix_fmt_bps_avi[] = { { AV_PIX_FMT_NONE, 0 }, }; -const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { +static const PixelFormatTag pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 1 }, { AV_PIX_FMT_PAL8, 2 }, { AV_PIX_FMT_PAL8, 4 }, @@ -337,3 +337,33 @@ const PixelFormatTag avpriv_pix_fmt_bps_mov[] = { { AV_PIX_FMT_PAL8, 33 }, { AV_PIX_FMT_NONE, 0 }, }; + +static enum AVPixelFormat find_pix_fmt(const PixelFormatTag *tags, + unsigned int fourcc) +{ + while (tags->pix_fmt != AV_PIX_FMT_NONE) { + if (tags->fourcc == fourcc) + return tags->pix_fmt; + tags++; + } + return AV_PIX_FMT_NONE; +} + +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc) +{ + const PixelFormatTag *tags; + + switch (list) { + case PIX_FMT_LIST_RAW: + tags = raw_pix_fmt_tags; + break; + case PIX_FMT_LIST_AVI: + tags = pix_fmt_bps_avi; + break; + case PIX_FMT_LIST_MOV: + tags = pix_fmt_bps_mov; + break; + } + return find_pix_fmt(tags, fourcc); +} diff --git a/libavcodec/raw.h b/libavcodec/raw.h index 6a041690b1..9a4ddef8fc 100644 --- a/libavcodec/raw.h +++ b/libavcodec/raw.h @@ -28,20 +28,21 @@ #define AVCODEC_RAW_H #include "libavutil/pixfmt.h" -#include "internal.h" typedef struct PixelFormatTag { enum AVPixelFormat pix_fmt; unsigned int fourcc; } PixelFormatTag; -extern const PixelFormatTag ff_raw_pix_fmt_tags[]; // exposed through avpriv_get_raw_pix_fmt_tags() - const struct PixelFormatTag *avpriv_get_raw_pix_fmt_tags(void); -enum AVPixelFormat avpriv_find_pix_fmt(const PixelFormatTag *tags, unsigned int fourcc); +enum PixelFormatTagLists { + PIX_FMT_LIST_RAW, + PIX_FMT_LIST_AVI, + PIX_FMT_LIST_MOV, +}; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_avi[]; -extern av_export_avcodec const PixelFormatTag avpriv_pix_fmt_bps_mov[]; +enum AVPixelFormat avpriv_pix_fmt_find(enum PixelFormatTagLists list, + unsigned fourcc); #endif /* AVCODEC_RAW_H */ diff --git a/libavcodec/rawdec.c b/libavcodec/rawdec.c index b22e36e984..9724cce13f 100644 --- a/libavcodec/rawdec.c +++ b/libavcodec/rawdec.c @@ -76,15 +76,15 @@ static av_cold int raw_init_decoder(AVCodecContext *avctx) if ( avctx->codec_tag == MKTAG('r','a','w',' ') || avctx->codec_tag == MKTAG('N','O','1','6')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, avctx->bits_per_coded_sample); else if (avctx->codec_tag == MKTAG('W', 'R', 'A', 'W')) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); else if (avctx->codec_tag && (avctx->codec_tag & 0xFFFFFF) != MKTAG('B','I','T', 0)) - avctx->pix_fmt = avpriv_find_pix_fmt(ff_raw_pix_fmt_tags, avctx->codec_tag); + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, avctx->codec_tag); else if (avctx->pix_fmt == AV_PIX_FMT_NONE && avctx->bits_per_coded_sample) - avctx->pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + avctx->pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, avctx->bits_per_coded_sample); desc = av_pix_fmt_desc_get(avctx->pix_fmt); diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c index 7e15084d71..561d992a46 100644 --- a/libavcodec/rawenc.c +++ b/libavcodec/rawenc.c @@ -85,7 +85,7 @@ const AVCodec ff_rawvideo_encoder = { .long_name = NULL_IF_CONFIG_SMALL("raw video"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_RAWVIDEO, - .capabilities = AV_CODEC_CAP_DR1, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .init = raw_encode_init, .encode2 = raw_encode, .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE, diff --git a/libavcodec/rl.c b/libavcodec/rl.c index fab96d63a1..4ce003ccf4 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,12 +53,9 @@ 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; } } diff --git a/libavcodec/rl.h b/libavcodec/rl.h index 5aae698e31..07e3da5003 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/roqvideoenc.c b/libavcodec/roqvideoenc.c index 684dbe0af5..95012f7c1a 100644 --- a/libavcodec/roqvideoenc.c +++ b/libavcodec/roqvideoenc.c @@ -666,7 +666,6 @@ static void reconstruct_and_encode_image(RoqEncContext *enc, int i, j, k; int x, y; int subX, subY; - int dist=0; roq_qcell *qcell; CelEvaluation *eval; @@ -692,7 +691,6 @@ static void reconstruct_and_encode_image(RoqEncContext *enc, x = eval->sourceX; y = eval->sourceY; - dist += eval->eval_dist[eval->best_coding]; switch (eval->best_coding) { case RoQ_ID_MOT: diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index d8261c34c7..0dc2c87335 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -149,7 +149,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 +297,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) diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c index 5b0035b244..52795efb5f 100644 --- a/libavcodec/smcenc.c +++ b/libavcodec/smcenc.c @@ -39,7 +39,6 @@ typedef struct SMCContext { AVFrame *prev_frame; // buffer for previous source frame - PutByteContext pb; uint8_t mono_value; int nb_distinct; @@ -110,9 +109,9 @@ static int count_distinct_items(const uint8_t *block_values, s->color_octets[i][6] == distinct_values[x] || \ s->color_octets[i][7] == distinct_values[x]) -static void smc_encode_stream(SMCContext *s, const AVFrame *frame) +static void smc_encode_stream(SMCContext *s, const AVFrame *frame, + PutByteContext *pb) { - PutByteContext *pb = &s->pb; const uint8_t *src_pixels = (const uint8_t *)frame->data[0]; const int stride = frame->linesize[0]; const uint8_t *prev_pixels = (const uint8_t *)s->prev_frame->data[0]; @@ -492,6 +491,7 @@ static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, { SMCContext *s = avctx->priv_data; const AVFrame *pict = frame; + PutByteContext pb; uint8_t *pal; int ret; @@ -506,18 +506,18 @@ static int smc_encode_frame(AVCodecContext *avctx, AVPacket *pkt, s->key_frame = 0; } - bytestream2_init_writer(&s->pb, pkt->data, pkt->size); + bytestream2_init_writer(&pb, pkt->data, pkt->size); - bytestream2_put_be32(&s->pb, 0x00); + bytestream2_put_be32(&pb, 0x00); pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); if (!pal) return AVERROR(ENOMEM); memcpy(pal, frame->data[1], AVPALETTE_SIZE); - smc_encode_stream(s, pict); + smc_encode_stream(s, pict, &pb); - av_shrink_packet(pkt, bytestream2_tell_p(&s->pb)); + av_shrink_packet(pkt, bytestream2_tell_p(&pb)); pkt->data[0] = 0x0; diff --git a/libavcodec/snow.c b/libavcodec/snow.c index e0fb58042c..0a500695ce 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -31,7 +31,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, diff --git a/libavcodec/snow.h b/libavcodec/snow.h index 8795491cf3..f5beca66e9 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/snowdec.c b/libavcodec/snowdec.c index cd2265aba1..d54036e02b 100644 --- a/libavcodec/snowdec.c +++ b/libavcodec/snowdec.c @@ -29,8 +29,6 @@ #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; diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c index 96b0d320bc..df31eb8132 100644 --- a/libavcodec/snowenc.c +++ b/libavcodec/snowenc.c @@ -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); diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c index 63a613f77d..cf1cfb1460 100644 --- a/libavcodec/sonic.c +++ b/libavcodec/sonic.c @@ -23,6 +23,7 @@ #include "get_bits.h" #include "golomb.h" #include "internal.h" +#include "put_golomb.h" #include "rangecoder.h" diff --git a/libavcodec/speedhq.c b/libavcodec/speedhq.c index 91ba80ebd3..743dacc6ce 100644 --- a/libavcodec/speedhq.c +++ b/libavcodec/speedhq.c @@ -295,7 +295,8 @@ static int decode_speedhq_border(const SHQContext *s, GetBitContext *gb, AVFrame if (s->subsampling == SHQ_SUBSAMPLING_420) { dest_cb = frame->data[1] + frame->linesize[1] * (y/2 + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y/2 + field_number) + x / 2; - } else if (s->subsampling == SHQ_SUBSAMPLING_422) { + } else { + av_assert2(s->subsampling == SHQ_SUBSAMPLING_422); dest_cb = frame->data[1] + frame->linesize[1] * (y + field_number) + x / 2; dest_cr = frame->data[2] + frame->linesize[2] * (y + field_number) + x / 2; } diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c index 4a2b422f13..967774931c 100644 --- a/libavcodec/speedhqenc.c +++ b/libavcodec/speedhqenc.c @@ -32,6 +32,7 @@ #include "avcodec.h" #include "mpeg12.h" +#include "mpeg12data.h" #include "mpegvideo.h" #include "speedhqenc.h" @@ -212,8 +213,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 +223,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]) diff --git a/libavcodec/speexdec.c b/libavcodec/speexdec.c index 4c50f54f27..dcbdf5e010 100644 --- a/libavcodec/speexdec.c +++ b/libavcodec/speexdec.c @@ -1221,7 +1221,7 @@ static int sb_decode(AVCodecContext *avctx, void *ptr_st, float low_pi_gain[NB_NB_SUBFRAMES]; float low_exc_rms[NB_NB_SUBFRAMES]; float interp_qlsp[NB_ORDER]; - int ret, wideband, dtx = 0; + int ret, wideband; float *low_innov_alias; float qlsp[NB_ORDER]; float ak[NB_ORDER]; @@ -1254,11 +1254,6 @@ static int sb_decode(AVCodecContext *avctx, void *ptr_st, /* If null mode (no transmission), just set a couple things to zero */ if (st->submodes[st->submodeID] == NULL) { - if (dtx) { - //sb_decode_lost(st, out, 1); - return 0; - } - for (int i = 0; i < st->frame_size; i++) out[st->frame_size + i] = 1e-15f; @@ -1424,11 +1419,13 @@ static int parse_speex_extradata(AVCodecContext *avctx, return AVERROR_INVALIDDATA; s->bitrate = bytestream_get_le32(&buf); s->frame_size = bytestream_get_le32(&buf); - if (s->frame_size < NB_FRAME_SIZE) + if (s->frame_size < NB_FRAME_SIZE << s->mode) return AVERROR_INVALIDDATA; s->vbr = bytestream_get_le32(&buf); s->frames_per_packet = bytestream_get_le32(&buf); - if (s->frames_per_packet <= 0) + if (s->frames_per_packet <= 0 || + s->frames_per_packet > 64 || + s->frames_per_packet >= INT32_MAX / s->nb_channels / s->frame_size) return AVERROR_INVALIDDATA; s->extra_headers = bytestream_get_le32(&buf); @@ -1548,7 +1545,7 @@ static int speex_decode_frame(AVCodecContext *avctx, void *data, if ((ret = init_get_bits8(&s->gb, avpkt->data, buf_size)) < 0) return ret; - frame->nb_samples = s->frame_size * s->frames_per_packet; + frame->nb_samples = FFALIGN(s->frame_size * s->frames_per_packet, 4); if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; @@ -1563,6 +1560,7 @@ static int speex_decode_frame(AVCodecContext *avctx, void *data, dst = (float *)frame->extended_data[0]; s->fdsp->vector_fmul_scalar(dst, dst, scale, frame->nb_samples * frame->channels); + frame->nb_samples = s->frame_size * s->frames_per_packet; *got_frame_ptr = 1; diff --git a/libavcodec/svq1dec.c b/libavcodec/svq1dec.c index a67d1866b6..a2b3f71c07 100644 --- a/libavcodec/svq1dec.c +++ b/libavcodec/svq1dec.c @@ -37,7 +37,7 @@ #include "avcodec.h" #include "get_bits.h" -#include "h263.h" +#include "h263data.h" #include "hpeldsp.h" #include "internal.h" #include "mathops.h" diff --git a/libavcodec/svq3.c b/libavcodec/svq3.c index e329578af0..a3f434ff8d 100644 --- a/libavcodec/svq3.c +++ b/libavcodec/svq3.c @@ -98,7 +98,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 +128,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 +637,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 +715,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 || @@ -1470,13 +1462,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; diff --git a/libavcodec/tak.h b/libavcodec/tak.h index dc45a8c070..6069118971 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/targa.c b/libavcodec/targa.c index 3502636c16..b0048621d3 100644 --- a/libavcodec/targa.c +++ b/libavcodec/targa.c @@ -117,6 +117,7 @@ static int decode_frame(AVCodecContext *avctx, int idlen, pal, compr, y, w, h, bpp, flags, ret; int first_clr, colors, csize; int interleave; + size_t img_size; bytestream2_init(&s->gb, avpkt->data, avpkt->size); @@ -176,6 +177,19 @@ static int decode_frame(AVCodecContext *avctx, if ((ret = ff_set_dimensions(avctx, w, h)) < 0) return ret; + if ((compr & (~TGA_RLE)) == TGA_NODATA) { + return avpkt->size; + } + + if (!(compr & TGA_RLE)) { + img_size = w * ((bpp + 1) >> 3); + if (bytestream2_get_bytes_left(&s->gb) < img_size * h) { + av_log(avctx, AV_LOG_ERROR, + "Not enough data available for image\n"); + return AVERROR_INVALIDDATA; + } + } + if ((ret = ff_get_buffer(avctx, p, 0)) < 0) return ret; p->pict_type = AV_PICTURE_TYPE_I; @@ -242,15 +256,11 @@ static int decode_frame(AVCodecContext *avctx, } } - if ((compr & (~TGA_RLE)) == TGA_NODATA) { - memset(p->data[0], 0, p->linesize[0] * h); - } else { if (compr & TGA_RLE) { int res = targa_decode_rle(avctx, s, dst, w, h, stride, bpp, interleave); if (res < 0) return res; } else { - size_t img_size = w * ((bpp + 1) >> 3); uint8_t *line; if (bytestream2_get_bytes_left(&s->gb) < img_size * h) { av_log(avctx, AV_LOG_ERROR, @@ -289,7 +299,6 @@ static int decode_frame(AVCodecContext *avctx, } } } - } *got_frame = 1; diff --git a/libavcodec/tests/.gitignore b/libavcodec/tests/.gitignore index 69bf891f44..2acfc4e804 100644 --- a/libavcodec/tests/.gitignore +++ b/libavcodec/tests/.gitignore @@ -1,3 +1,4 @@ +/avcodec /avfft /avpacket /cabac @@ -18,4 +19,3 @@ /mpeg12framerate /rangecoder /snowenc -/utils diff --git a/libavcodec/tests/golomb.c b/libavcodec/tests/golomb.c index 85b8a9390b..061cc013ce 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/tiff.c b/libavcodec/tiff.c index 870e0666aa..fd85d104dc 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -721,19 +721,6 @@ static int dng_decode_jpeg(AVCodecContext *avctx, AVFrame *frame, return 0; } -static int dng_decode_strip(AVCodecContext *avctx, AVFrame *frame) -{ - TiffContext *s = avctx->priv_data; - - s->jpgframe->width = s->width; - s->jpgframe->height = s->height; - - s->avctx_mjpeg->width = s->width; - s->avctx_mjpeg->height = s->height; - - return dng_decode_jpeg(avctx, frame, s->stripsize, 0, 0, s->width, s->height); -} - static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int stride, const uint8_t *src, int size, int strip_start, int lines) { @@ -855,7 +842,7 @@ 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 ((ret = dng_decode_strip(s->avctx, p)) < 0) + if ((ret = dng_decode_jpeg(s->avctx, p, s->stripsize, 0, 0, s->width, s->height)) < 0) return ret; return 0; } @@ -973,12 +960,6 @@ static int dng_decode_tiles(AVCodecContext *avctx, AVFrame *frame, int pos_x = 0, pos_y = 0; int ret; - s->jpgframe->width = s->tile_width; - s->jpgframe->height = s->tile_length; - - s->avctx_mjpeg->width = s->tile_width; - s->avctx_mjpeg->height = s->tile_length; - has_width_leftover = (s->width % s->tile_width != 0); has_height_leftover = (s->height % s->tile_length != 0); @@ -2155,6 +2136,7 @@ static av_cold int tiff_init(AVCodecContext *avctx) s->avctx_mjpeg->flags2 = avctx->flags2; s->avctx_mjpeg->dct_algo = avctx->dct_algo; s->avctx_mjpeg->idct_algo = avctx->idct_algo; + s->avctx_mjpeg->max_pixels = avctx->max_pixels; ret = avcodec_open2(s->avctx_mjpeg, codec, NULL); if (ret < 0) { return ret; diff --git a/libavcodec/to_upper4.c b/libavcodec/to_upper4.c new file mode 100644 index 0000000000..29f65bf5c3 --- /dev/null +++ b/libavcodec/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 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 "to_upper4.h" diff --git a/libavcodec/to_upper4.h b/libavcodec/to_upper4.h new file mode 100644 index 0000000000..d9648b5ef6 --- /dev/null +++ b/libavcodec/to_upper4.h @@ -0,0 +1,37 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 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 + */ + +#ifndef AVCODEC_TO_UPPER4_H +#define AVCODEC_TO_UPPER4_H + +#include "libavutil/avstring.h" +#include "internal.h" + +unsigned int ff_toupper4(unsigned int x) +{ + return av_toupper(x & 0xFF) | + (av_toupper((x >> 8) & 0xFF) << 8) | + (av_toupper((x >> 16) & 0xFF) << 16) | +((unsigned)av_toupper((x >> 24) & 0xFF) << 24); +} + +#endif diff --git a/libavcodec/ttadsp.c b/libavcodec/ttadsp.c index 1d1443aee0..99dd66a0c2 100644 --- a/libavcodec/ttadsp.c +++ b/libavcodec/ttadsp.c @@ -47,9 +47,9 @@ static void tta_filter_process_c(int32_t *qmi, int32_t *dx, int32_t *dl, *error = *in; *in += (round >> shift); - dl[4] = -dl[5]; dl[5] = -dl[6]; - dl[6] = *in - dl[7]; dl[7] = *in; - dl[5] += dl[6]; dl[4] += dl[5]; + dl[4] = -(unsigned)dl[5]; dl[5] = -(unsigned)dl[6]; + dl[6] = *in -(unsigned)dl[7]; dl[7] = *in; + dl[5] += (unsigned)dl[6]; dl[4] += (unsigned)dl[5]; } av_cold void ff_ttadsp_init(TTADSPContext *c) diff --git a/libavcodec/txd.c b/libavcodec/txd.c index 86d60f3377..93e4fa9605 100644 --- a/libavcodec/txd.c +++ b/libavcodec/txd.c @@ -65,8 +65,26 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, if (depth == 8) { avctx->pix_fmt = AV_PIX_FMT_PAL8; - } else if (depth == 16 || depth == 32) { + if (bytestream2_get_bytes_left(&gb) < w * h + 4 * 256) + return AVERROR_INVALIDDATA; + } else if (depth == 16) { avctx->pix_fmt = AV_PIX_FMT_RGBA; + switch (d3d_format) { + case 0: + if (!(flags & 1)) + goto unsupported; + case TXD_DXT1: + if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 8 + 4) + return AVERROR_INVALIDDATA; + break; + case TXD_DXT3: + if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16 + 4) + return AVERROR_INVALIDDATA; + } + } else if (depth == 32) { + avctx->pix_fmt = AV_PIX_FMT_RGBA; + if (bytestream2_get_bytes_left(&gb) < h * w * 4) + return AVERROR_INVALIDDATA; } else { avpriv_report_missing_feature(avctx, "Color depth of %u", depth); return AVERROR_PATCHWELCOME; @@ -92,8 +110,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, v = bytestream2_get_be32(&gb); pal[y] = (v >> 8) + (v << 24); } - if (bytestream2_get_bytes_left(&gb) < w * h) - return AVERROR_INVALIDDATA; bytestream2_skip(&gb, 4); for (y=0; yheight; j += 4) { for (i = 0; i < avctx->width; i += 4) { uint8_t *p = ptr + i * 4 + j * stride; @@ -117,8 +129,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } break; case TXD_DXT3: - if (bytestream2_get_bytes_left(&gb) < AV_CEIL_RSHIFT(w, 2) * AV_CEIL_RSHIFT(h, 2) * 16) - return AVERROR_INVALIDDATA; for (j = 0; j < avctx->height; j += 4) { for (i = 0; i < avctx->width; i += 4) { uint8_t *p = ptr + i * 4 + j * stride; @@ -134,8 +144,6 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, switch (d3d_format) { case 0x15: case 0x16: - if (bytestream2_get_bytes_left(&gb) < h * w * 4) - return AVERROR_INVALIDDATA; for (y=0; ypix_fmt >= 0) { - if (tags->fourcc == fourcc) - return tags->pix_fmt; - tags++; - } - return AV_PIX_FMT_NONE; -} - int avpriv_codec_get_cap_skip_frame_fill_param(const AVCodec *codec){ return !!(codec->caps_internal & FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM); } @@ -874,14 +863,6 @@ const AVCodecHWConfig *avcodec_get_hw_config(const AVCodec *codec, int index) return &codec->hw_configs[index]->public; } -unsigned int avpriv_toupper4(unsigned int x) -{ - return av_toupper(x & 0xFF) + - (av_toupper((x >> 8) & 0xFF) << 8) + - (av_toupper((x >> 16) & 0xFF) << 16) + -((unsigned)av_toupper((x >> 24) & 0xFF) << 24); -} - int ff_thread_ref_frame(ThreadFrame *dst, const ThreadFrame *src) { int ret; diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c index 22875be7d5..16c4f82cf2 100644 --- a/libavcodec/v210enc.c +++ b/libavcodec/v210enc.c @@ -156,7 +156,7 @@ const AVCodec ff_v210_encoder = { .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, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS, .priv_data_size = sizeof(V210EncContext), .init = encode_init, .encode2 = encode_frame, diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index ff1ea8e57b..e891649f92 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -153,6 +153,21 @@ static inline void v4l2_save_to_context(V4L2Context* ctx, struct v4l2_format_upd } } +static int v4l2_start_decode(V4L2Context *ctx) +{ + struct v4l2_decoder_cmd cmd = { + .cmd = V4L2_DEC_CMD_START, + .flags = 0, + }; + int ret; + + ret = ioctl(ctx_to_m2mctx(ctx)->fd, VIDIOC_DECODER_CMD, &cmd); + if (ret) + return AVERROR(errno); + + return 0; +} + /** * handle resolution change event and end of stream event * returns 1 if reinit was successful, negative if it failed @@ -162,9 +177,8 @@ static int v4l2_handle_event(V4L2Context *ctx) { V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_format cap_fmt = s->capture.format; - struct v4l2_format out_fmt = s->output.format; struct v4l2_event evt = { 0 }; - int full_reinit, reinit, ret; + int ret; ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); if (ret < 0) { @@ -180,63 +194,35 @@ static int v4l2_handle_event(V4L2Context *ctx) if (evt.type != V4L2_EVENT_SOURCE_CHANGE) return 0; - ret = ioctl(s->fd, VIDIOC_G_FMT, &out_fmt); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->output.name); - return 0; - } - ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt); if (ret) { av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_G_FMT\n", s->capture.name); return 0; } - full_reinit = v4l2_resolution_changed(&s->output, &out_fmt); - if (full_reinit) { - s->output.height = v4l2_get_height(&out_fmt); - s->output.width = v4l2_get_width(&out_fmt); - s->output.sample_aspect_ratio = v4l2_get_sar(&s->output); - } - - 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); + } else { + v4l2_start_decode(ctx); + return 0; } - if (full_reinit || reinit) - s->reinit = 1; + s->reinit = 1; - if (full_reinit) { - ret = ff_v4l2_m2m_codec_full_reinit(s); - if (ret) { - av_log(logger(ctx), AV_LOG_ERROR, "v4l2_m2m_codec_full_reinit\n"); - return AVERROR(EINVAL); - } - goto reinit_run; + 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); } - 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"); - - 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; - } - - /* dummy event received */ - return 0; - /* reinit executed */ -reinit_run: return 1; } diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 224eb3d5e7..b0c3d30ac8 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -142,8 +142,12 @@ static int v4l2_receive_frame(AVCodecContext *avctx, AVFrame *frame) if (!s->buf_pkt.size) { ret = ff_decode_get_packet(avctx, &s->buf_pkt); - if (ret < 0 && ret != AVERROR_EOF) - return ret; + if (ret < 0) { + if (ret == AVERROR(EAGAIN)) + return ff_v4l2_context_dequeue_frame(capture, frame, 0); + else if (ret != AVERROR_EOF) + return ret; + } } if (s->draining) diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index ec054ae701..3bf379b1a0 100644 --- a/libavcodec/vaapi_encode.c +++ b/libavcodec/vaapi_encode.c @@ -2366,6 +2366,11 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) VAStatus vas; int err; + ctx->va_config = VA_INVALID_ID; + ctx->va_context = VA_INVALID_ID; + + /* If you add something that can fail above this av_frame_alloc(), + * modify ff_vaapi_encode_close() accordingly. */ ctx->frame = av_frame_alloc(); if (!ctx->frame) { return AVERROR(ENOMEM); @@ -2377,9 +2382,6 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) return AVERROR(EINVAL); } - ctx->va_config = VA_INVALID_ID; - ctx->va_context = VA_INVALID_ID; - ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx); if (!ctx->input_frames_ref) { err = AVERROR(ENOMEM); @@ -2531,6 +2533,11 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodePicture *pic, *next; + /* We check ctx->frame to know whether ff_vaapi_encode_init() + * has been called and va_config/va_context initialized. */ + if (!ctx->frame) + return 0; + for (pic = ctx->pic_start; pic; pic = next) { next = pic->next; vaapi_encode_free(avctx, pic); diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index d35f416ad7..6206b23e5f 100644 --- a/libavcodec/vaapi_encode_mjpeg.c +++ b/libavcodec/vaapi_encode_mjpeg.c @@ -327,20 +327,20 @@ static int vaapi_encode_mjpeg_init_picture_params(AVCodecContext *avctx, switch (t) { case 0: - lengths = avpriv_mjpeg_bits_dc_luminance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_luminance + 1; + values = ff_mjpeg_val_dc; break; case 1: - lengths = avpriv_mjpeg_bits_ac_luminance + 1; - values = avpriv_mjpeg_val_ac_luminance; + lengths = ff_mjpeg_bits_ac_luminance + 1; + values = ff_mjpeg_val_ac_luminance; break; case 2: - lengths = avpriv_mjpeg_bits_dc_chrominance + 1; - values = avpriv_mjpeg_val_dc; + lengths = ff_mjpeg_bits_dc_chrominance + 1; + values = ff_mjpeg_val_dc; break; case 3: - lengths = avpriv_mjpeg_bits_ac_chrominance + 1; - values = avpriv_mjpeg_val_ac_chrominance; + lengths = ff_mjpeg_bits_ac_chrominance + 1; + values = ff_mjpeg_val_ac_chrominance; break; } diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c index b3f45fb8fe..be706e3bd6 100644 --- a/libavcodec/vaapi_encode_vp9.c +++ b/libavcodec/vaapi_encode_vp9.c @@ -31,6 +31,7 @@ #define VP9_MAX_QUANT 255 +#define VP9_MAX_TILE_WIDTH 4096 typedef struct VAAPIEncodeVP9Picture { int slot; @@ -82,10 +83,17 @@ static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx, VAAPIEncodeVP9Picture *hpic = pic->priv_data; VAEncPictureParameterBufferVP9 *vpic = pic->codec_picture_params; int i; + int num_tile_columns; vpic->reconstructed_frame = pic->recon_surface; vpic->coded_buf = pic->output_buffer; + // Maximum width of a tile in units of superblocks is MAX_TILE_WIDTH_B64(64) + // So the number of tile columns is related to the width of the picture. + // We set the minimum possible number for num_tile_columns as default value. + num_tile_columns = (vpic->frame_width_src + VP9_MAX_TILE_WIDTH - 1) / VP9_MAX_TILE_WIDTH; + vpic->log2_tile_columns = num_tile_columns == 1 ? 0 : av_log2(num_tile_columns - 1) + 1; + switch (pic->type) { case PICTURE_TYPE_IDR: av_assert0(pic->nb_refs == 0); diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index e636fa6160..7ed5133cfa 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -862,7 +862,7 @@ static int vc1_decode_frame(AVCodecContext *avctx, void *data, s->current_picture.f->key_frame = s->pict_type == AV_PICTURE_TYPE_I; /* skip B-frames if we don't have reference frames */ - if (!s->last_picture_ptr && (s->pict_type == AV_PICTURE_TYPE_B || s->droppable)) { + if (!s->last_picture_ptr && s->pict_type == AV_PICTURE_TYPE_B) { av_log(v->s.avctx, AV_LOG_DEBUG, "Skipping B frame without reference frames\n"); goto end; } @@ -872,13 +872,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; } diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c index c25a6f3adf..04fc8b12f3 100644 --- a/libavcodec/vc1dsp.c +++ b/libavcodec/vc1dsp.c @@ -1039,4 +1039,6 @@ av_cold void ff_vc1dsp_init(VC1DSPContext *dsp) ff_vc1dsp_init_x86(dsp); if (ARCH_MIPS) ff_vc1dsp_init_mips(dsp); + if (ARCH_LOONGARCH) + ff_vc1dsp_init_loongarch(dsp); } diff --git a/libavcodec/vc1dsp.h b/libavcodec/vc1dsp.h index 75db62b1b4..c6443acb20 100644 --- a/libavcodec/vc1dsp.h +++ b/libavcodec/vc1dsp.h @@ -88,5 +88,6 @@ void ff_vc1dsp_init_arm(VC1DSPContext* dsp); void ff_vc1dsp_init_ppc(VC1DSPContext *c); void ff_vc1dsp_init_x86(VC1DSPContext* dsp); void ff_vc1dsp_init_mips(VC1DSPContext* dsp); +void ff_vc1dsp_init_loongarch(VC1DSPContext* dsp); #endif /* AVCODEC_VC1DSP_H */ diff --git a/libavcodec/version.h b/libavcodec/version.h index 74b8baa5f3..a46fb05f1a 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,7 +28,7 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 59 -#define LIBAVCODEC_VERSION_MINOR 12 +#define LIBAVCODEC_VERSION_MINOR 20 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ @@ -51,41 +51,18 @@ * at once through the bump. This improves the git bisect-ability of the change. */ -#ifndef FF_API_OPENH264_SLICE_MODE #define FF_API_OPENH264_SLICE_MODE (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_OPENH264_CABAC #define FF_API_OPENH264_CABAC (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_UNUSED_CODEC_CAPS #define FF_API_UNUSED_CODEC_CAPS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_THREAD_SAFE_CALLBACKS #define FF_API_THREAD_SAFE_CALLBACKS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_DEBUG_MV #define FF_API_DEBUG_MV (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_GET_FRAME_CLASS #define FF_API_GET_FRAME_CLASS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_AUTO_THREADS #define FF_API_AUTO_THREADS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_INIT_PACKET #define FF_API_INIT_PACKET (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_AVCTX_TIMEBASE #define FF_API_AVCTX_TIMEBASE (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_MPEGVIDEO_OPTS #define FF_API_MPEGVIDEO_OPTS (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_FLAG_TRUNCATED #define FF_API_FLAG_TRUNCATED (LIBAVCODEC_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_SUB_TEXT_FORMAT #define FF_API_SUB_TEXT_FORMAT (LIBAVCODEC_VERSION_MAJOR < 60) -#endif +#define FF_API_MJPEG_PRED (LIBAVCODEC_VERSION_MAJOR < 60) #endif /* AVCODEC_VERSION_H */ diff --git a/libavcodec/videodsp.c b/libavcodec/videodsp.c index ce9e9eb143..212147984f 100644 --- a/libavcodec/videodsp.c +++ b/libavcodec/videodsp.c @@ -54,4 +54,6 @@ av_cold void ff_videodsp_init(VideoDSPContext *ctx, int bpc) ff_videodsp_init_x86(ctx, bpc); if (ARCH_MIPS) ff_videodsp_init_mips(ctx, bpc); + if (ARCH_LOONGARCH64) + ff_videodsp_init_loongarch(ctx, bpc); } diff --git a/libavcodec/videodsp.h b/libavcodec/videodsp.h index c0545f22b0..ac971dc57f 100644 --- a/libavcodec/videodsp.h +++ b/libavcodec/videodsp.h @@ -84,5 +84,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/videotoolbox.c b/libavcodec/videotoolbox.c index 49e726a75f..51d4eacfd8 100644 --- a/libavcodec/videotoolbox.c +++ b/libavcodec/videotoolbox.c @@ -32,6 +32,9 @@ #include "h264dec.h" #include "hevcdec.h" #include "mpegvideo.h" +#include "proresdec.h" +#include +#include #include #ifndef kVTVideoDecoderSpecification_RequireHardwareAcceleratedVideoDecoder @@ -45,6 +48,10 @@ enum { kCMVideoCodecType_HEVC = 'hvc1' }; #endif +#if !HAVE_KCMVIDEOCODECTYPE_VP9 +enum { kCMVideoCodecType_VP9 = 'vp09' }; +#endif + #define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING 12 typedef struct VTHWFrame { @@ -61,9 +68,9 @@ static void videotoolbox_buffer_release(void *opaque, uint8_t *data) av_free(data); } -static int videotoolbox_buffer_copy(VTContext *vtctx, - const uint8_t *buffer, - uint32_t size) +int ff_videotoolbox_buffer_copy(VTContext *vtctx, + const uint8_t *buffer, + uint32_t size) { void *tmp; @@ -83,6 +90,7 @@ static int videotoolbox_buffer_copy(VTContext *vtctx, static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) { + int ret; VTHWFrame *ref = (VTHWFrame *)frame->buf[0]->data; if (!ref->pixbuf) { @@ -96,6 +104,9 @@ static int videotoolbox_postproc_frame(void *avctx, AVFrame *frame) frame->crop_top = 0; frame->crop_bottom = 0; + if ((ret = av_vt_pixbuf_set_attachments(avctx, ref->pixbuf, frame)) < 0) + return ret; + frame->data[3] = (uint8_t*)ref->pixbuf; if (ref->hw_frames_ctx) { @@ -140,14 +151,50 @@ int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame) #define AV_W8(p, v) *(p) = (v) +static int escape_ps(uint8_t* dst, const uint8_t* src, int src_size) +{ + int i; + int size = src_size; + uint8_t* p = dst; + + for (i = 0; i < src_size; i++) { + if (i + 2 < src_size && + src[i] == 0x00 && + src[i + 1] == 0x00 && + src[i + 2] <= 0x03) { + if (dst) { + *p++ = src[i++]; + *p++ = src[i++]; + *p++ = 0x03; + } else { + i += 2; + } + size++; + } + if (dst) + *p++ = src[i]; + } + + if (dst) + av_assert0((p - dst) == size); + + return size; +} + CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; H264Context *h = avctx->priv_data; CFDataRef data = NULL; uint8_t *p; - int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size; - uint8_t *vt_extradata = av_malloc(vt_extradata_size); + int sps_size = escape_ps(NULL, h->ps.sps->data, h->ps.sps->data_size); + int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size); + int vt_extradata_size; + uint8_t *vt_extradata; + + vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size; + vt_extradata = av_malloc(vt_extradata_size); + if (!vt_extradata) return NULL; @@ -159,14 +206,14 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx) AV_W8(p + 3, h->ps.sps->data[3]); /* level */ AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */ AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ - AV_WB16(p + 6, h->ps.sps->data_size); - memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size); - p += 8 + h->ps.sps->data_size; + AV_WB16(p + 6, sps_size); + p += 8; + p += escape_ps(p, h->ps.sps->data, h->ps.sps->data_size); AV_W8(p + 0, 1); /* number of pps */ - AV_WB16(p + 1, h->ps.pps->data_size); - memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size); + AV_WB16(p + 1, pps_size); + p += 3; + p += escape_ps(p, h->ps.pps->data, h->ps.pps->data_size); - p += 3 + h->ps.pps->data_size; av_assert0(p - vt_extradata == vt_extradata_size); // save sps header (profile/level) used to create decoder session, @@ -339,7 +386,7 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, H264Context *h = avctx->priv_data; if (h->is_avc == 1) { - return videotoolbox_buffer_copy(vtctx, buffer, size); + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); } return 0; @@ -403,18 +450,6 @@ int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, return videotoolbox_common_decode_slice(avctx, buffer, size); } -int ff_videotoolbox_uninit(AVCodecContext *avctx) -{ - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (vtctx) { - av_freep(&vtctx->bitstream); - if (vtctx->frame) - CVPixelBufferRelease(vtctx->frame); - } - - return 0; -} - #if CONFIG_VIDEOTOOLBOX // Return the AVVideotoolboxContext that matters currently. Where it comes from // depends on the API used. @@ -430,6 +465,43 @@ static AVVideotoolboxContext *videotoolbox_get_context(AVCodecContext *avctx) return avctx->hwaccel_context; } +static void videotoolbox_stop(AVCodecContext *avctx) +{ + AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); + if (!videotoolbox) + return; + + if (videotoolbox->cm_fmt_desc) { + CFRelease(videotoolbox->cm_fmt_desc); + videotoolbox->cm_fmt_desc = NULL; + } + + if (videotoolbox->session) { + VTDecompressionSessionInvalidate(videotoolbox->session); + CFRelease(videotoolbox->session); + videotoolbox->session = NULL; + } +} + +int ff_videotoolbox_uninit(AVCodecContext *avctx) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + if (!vtctx) + return 0; + + av_freep(&vtctx->bitstream); + if (vtctx->frame) + CVPixelBufferRelease(vtctx->frame); + + if (vtctx->vt_ctx) + videotoolbox_stop(avctx); + + av_buffer_unref(&vtctx->cached_hw_frames_ctx); + av_freep(&vtctx->vt_ctx); + + return 0; +} + static int videotoolbox_buffer_create(AVCodecContext *avctx, AVFrame *frame) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; @@ -753,6 +825,13 @@ static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec if (data) CFDictionarySetValue(avc_info, CFSTR("hvcC"), data); break; +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + case kCMVideoCodecType_VP9 : + data = ff_videotoolbox_vpcc_extradata_create(avctx); + if (data) + CFDictionarySetValue(avc_info, CFSTR("vpcC"), data); + break; +#endif default: break; } @@ -800,10 +879,42 @@ static int videotoolbox_start(AVCodecContext *avctx) case AV_CODEC_ID_MPEG4 : videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video; break; + case AV_CODEC_ID_PRORES : + switch (avctx->codec_tag) { + default: + av_log(avctx, AV_LOG_WARNING, "Unknown prores profile %d\n", avctx->codec_tag); + // fall-through + case MKTAG('a','p','c','o'): // kCMVideoCodecType_AppleProRes422Proxy + case MKTAG('a','p','c','s'): // kCMVideoCodecType_AppleProRes422LT + case MKTAG('a','p','c','n'): // kCMVideoCodecType_AppleProRes422 + case MKTAG('a','p','c','h'): // kCMVideoCodecType_AppleProRes422HQ + case MKTAG('a','p','4','h'): // kCMVideoCodecType_AppleProRes4444 + case MKTAG('a','p','4','x'): // kCMVideoCodecType_AppleProRes4444XQ + videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag); + break; + } + break; + case AV_CODEC_ID_VP9 : + videotoolbox->cm_codec_type = kCMVideoCodecType_VP9; + break; default : break; } +#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) && AV_HAS_BUILTIN(__builtin_available) + if (avctx->codec_id == AV_CODEC_ID_PRORES) { + if (__builtin_available(macOS 10.9, *)) { + VTRegisterProfessionalVideoWorkflowVideoDecoders(); + } + } +#endif + +#if defined(MAC_OS_VERSION_11_0) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_VERSION_11_0) && AV_HAS_BUILTIN(__builtin_available) + if (__builtin_available(macOS 11.0, *)) { + VTRegisterSupplementalVideoDecoderIfAvailable(videotoolbox->cm_codec_type); + } +#endif + decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx); if (!decoder_spec) { @@ -866,24 +977,6 @@ static int videotoolbox_start(AVCodecContext *avctx) } } -static void videotoolbox_stop(AVCodecContext *avctx) -{ - AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); - if (!videotoolbox) - return; - - if (videotoolbox->cm_fmt_desc) { - CFRelease(videotoolbox->cm_fmt_desc); - videotoolbox->cm_fmt_desc = NULL; - } - - if (videotoolbox->session) { - VTDecompressionSessionInvalidate(videotoolbox->session); - CFRelease(videotoolbox->session); - videotoolbox->session = NULL; - } -} - static const char *videotoolbox_error_string(OSStatus status) { switch (status) { @@ -897,7 +990,7 @@ static const char *videotoolbox_error_string(OSStatus status) return "unknown"; } -static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) +int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame) { OSStatus status; AVVideotoolboxContext *videotoolbox = videotoolbox_get_context(avctx); @@ -936,7 +1029,7 @@ static int videotoolbox_h264_end_frame(AVCodecContext *avctx) H264Context *h = avctx->priv_data; AVFrame *frame = h->cur_pic_ptr->f; VTContext *vtctx = avctx->internal->hwaccel_priv_data; - int ret = videotoolbox_common_end_frame(avctx, frame); + int ret = ff_videotoolbox_common_end_frame(avctx, frame); vtctx->bitstream_size = 0; return ret; } @@ -975,7 +1068,7 @@ static int videotoolbox_hevc_end_frame(AVCodecContext *avctx) h->output_frame->crop_top = 0; h->output_frame->crop_bottom = 0; - int ret = videotoolbox_common_end_frame(avctx, frame); + int ret = ff_videotoolbox_common_end_frame(avctx, frame); vtctx->bitstream_size = 0; return ret; } @@ -986,7 +1079,7 @@ static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx, { VTContext *vtctx = avctx->internal->hwaccel_priv_data; - return videotoolbox_buffer_copy(vtctx, buffer, size); + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); } static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx, @@ -1001,40 +1094,76 @@ static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx) MpegEncContext *s = avctx->priv_data; AVFrame *frame = s->current_picture_ptr->f; - return videotoolbox_common_end_frame(avctx, frame); + return ff_videotoolbox_common_end_frame(avctx, frame); } -static int videotoolbox_uninit(AVCodecContext *avctx) +static int videotoolbox_prores_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) { - VTContext *vtctx = avctx->internal->hwaccel_priv_data; - if (!vtctx) - return 0; - - ff_videotoolbox_uninit(avctx); - - if (vtctx->vt_ctx) - videotoolbox_stop(avctx); - - av_buffer_unref(&vtctx->cached_hw_frames_ctx); - av_freep(&vtctx->vt_ctx); - return 0; } +static int videotoolbox_prores_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); +} + +static int videotoolbox_prores_end_frame(AVCodecContext *avctx) +{ + ProresContext *ctx = avctx->priv_data; + AVFrame *frame = ctx->frame; + + return ff_videotoolbox_common_end_frame(avctx, frame); +} + static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { - const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt); + const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->sw_pix_fmt); if (!descriptor) return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() int depth = descriptor->comp[0].depth; + + if (descriptor->flags & AV_PIX_FMT_FLAG_ALPHA) + return AV_PIX_FMT_AYUV64; + +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + if (depth > 10) + return descriptor->log2_chroma_w == 0 ? AV_PIX_FMT_P416 : AV_PIX_FMT_P216; +#endif + +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + if (descriptor->log2_chroma_w == 0) { +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + if (depth <= 8) + return AV_PIX_FMT_NV24; +#endif + return AV_PIX_FMT_P410; + } +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + if (descriptor->log2_chroma_h == 0) { +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + if (depth <= 8) + return AV_PIX_FMT_NV16; +#endif + return AV_PIX_FMT_P210; + } +#endif +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE if (depth > 8) { return AV_PIX_FMT_P010; } +#endif return AV_PIX_FMT_NV12; } -static int videotoolbox_common_init(AVCodecContext *avctx) +int ff_videotoolbox_common_init(AVCodecContext *avctx) { VTContext *vtctx = avctx->internal->hwaccel_priv_data; AVHWFramesContext *hw_frames; @@ -1106,12 +1235,12 @@ static int videotoolbox_common_init(AVCodecContext *avctx) return 0; fail: - videotoolbox_uninit(avctx); + ff_videotoolbox_uninit(avctx); return err; } -static int videotoolbox_frame_params(AVCodecContext *avctx, - AVBufferRef *hw_frames_ctx) +int ff_videotoolbox_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx) { AVHWFramesContext *frames_ctx = (AVHWFramesContext*)hw_frames_ctx->data; @@ -1132,9 +1261,9 @@ const AVHWAccel ff_h263_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1148,9 +1277,9 @@ const AVHWAccel ff_hevc_videotoolbox_hwaccel = { .decode_slice = videotoolbox_hevc_decode_slice, .decode_params = videotoolbox_hevc_decode_params, .end_frame = videotoolbox_hevc_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1164,9 +1293,9 @@ const AVHWAccel ff_h264_videotoolbox_hwaccel = { .decode_slice = ff_videotoolbox_h264_decode_slice, .decode_params = videotoolbox_h264_decode_params, .end_frame = videotoolbox_h264_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1179,9 +1308,9 @@ const AVHWAccel ff_mpeg1_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1194,9 +1323,9 @@ const AVHWAccel ff_mpeg2_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; @@ -1209,9 +1338,24 @@ const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = { .start_frame = videotoolbox_mpeg_start_frame, .decode_slice = videotoolbox_mpeg_decode_slice, .end_frame = videotoolbox_mpeg_end_frame, - .frame_params = videotoolbox_frame_params, - .init = videotoolbox_common_init, - .uninit = videotoolbox_uninit, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), +}; + +const AVHWAccel ff_prores_videotoolbox_hwaccel = { + .name = "prores_videotoolbox", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_PRORES, + .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, + .alloc_frame = ff_videotoolbox_alloc_frame, + .start_frame = videotoolbox_prores_start_frame, + .decode_slice = videotoolbox_prores_decode_slice, + .end_frame = videotoolbox_prores_end_frame, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, .priv_data_size = sizeof(VTContext), }; diff --git a/libavcodec/videotoolbox_vp9.c b/libavcodec/videotoolbox_vp9.c new file mode 100644 index 0000000000..1b6d08f00b --- /dev/null +++ b/libavcodec/videotoolbox_vp9.c @@ -0,0 +1,140 @@ +/* + * Videotoolbox hardware acceleration for VP9 + * + * copyright (c) 2021 rcombs + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "videotoolbox.h" +#include "libavutil/hwcontext_videotoolbox.h" +#include "vt_internal.h" +#include "libavutil/avutil.h" +#include "libavutil/frame.h" +#include "libavutil/hwcontext.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/pixdesc.h" +#include "decode.h" +#include "internal.h" +#include "vp9shared.h" + +enum VPX_CHROMA_SUBSAMPLING +{ + VPX_SUBSAMPLING_420_VERTICAL = 0, + VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA = 1, + VPX_SUBSAMPLING_422 = 2, + VPX_SUBSAMPLING_444 = 3, +}; + +static int get_vpx_chroma_subsampling(enum AVPixelFormat pixel_format, + enum AVChromaLocation chroma_location) +{ + int chroma_w, chroma_h; + if (av_pix_fmt_get_chroma_sub_sample(pixel_format, &chroma_w, &chroma_h) == 0) { + if (chroma_w == 1 && chroma_h == 1) { + return (chroma_location == AVCHROMA_LOC_LEFT) + ? VPX_SUBSAMPLING_420_VERTICAL + : VPX_SUBSAMPLING_420_COLLOCATED_WITH_LUMA; + } else if (chroma_w == 1 && chroma_h == 0) { + return VPX_SUBSAMPLING_422; + } else if (chroma_w == 0 && chroma_h == 0) { + return VPX_SUBSAMPLING_444; + } + } + return -1; +} + +CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx) +{ + const VP9SharedContext *h = avctx->priv_data; + CFDataRef data = NULL; + uint8_t *p; + int vt_extradata_size; + uint8_t *vt_extradata; + int subsampling = get_vpx_chroma_subsampling(avctx->sw_pix_fmt, avctx->chroma_sample_location); + + vt_extradata_size = 1 + 3 + 6 + 2; + vt_extradata = av_malloc(vt_extradata_size); + + if (subsampling < 0) + return NULL; + + if (!vt_extradata) + return NULL; + + p = vt_extradata; + + *p++ = 1; /* version */ + AV_WB24(p + 1, 0); /* flags */ + p += 3; + + *p++ = h->h.profile; + *p++ = avctx->level; + *p++ = (h->h.bpp << 4) | (subsampling << 1) | (avctx->color_range == AVCOL_RANGE_JPEG); + *p++ = avctx->color_primaries; + *p++ = avctx->color_trc; + *p++ = avctx->colorspace; + + AV_WB16(p + 0, 0); + p += 2; + + av_assert0(p - vt_extradata == vt_extradata_size); + + data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size); + av_free(vt_extradata); + return data; +} + +static int videotoolbox_vp9_start_frame(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + return 0; +} + +static int videotoolbox_vp9_decode_slice(AVCodecContext *avctx, + const uint8_t *buffer, + uint32_t size) +{ + VTContext *vtctx = avctx->internal->hwaccel_priv_data; + + return ff_videotoolbox_buffer_copy(vtctx, buffer, size); +} + +static int videotoolbox_vp9_end_frame(AVCodecContext *avctx) +{ + const VP9SharedContext *h = avctx->priv_data; + AVFrame *frame = h->frames[CUR_FRAME].tf.f; + + return ff_videotoolbox_common_end_frame(avctx, frame); +} + +const AVHWAccel ff_vp9_videotoolbox_hwaccel = { + .name = "vp9_videotoolbox", + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_VP9, + .pix_fmt = AV_PIX_FMT_VIDEOTOOLBOX, + .alloc_frame = ff_videotoolbox_alloc_frame, + .start_frame = videotoolbox_vp9_start_frame, + .decode_slice = videotoolbox_vp9_decode_slice, + .end_frame = videotoolbox_vp9_end_frame, + .frame_params = ff_videotoolbox_frame_params, + .init = ff_videotoolbox_common_init, + .uninit = ff_videotoolbox_uninit, + .priv_data_size = sizeof(VTContext), +}; diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index bac36fda90..418ff00b8d 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -29,6 +29,7 @@ #include "libavutil/avstring.h" #include "libavcodec/avcodec.h" #include "libavutil/pixdesc.h" +#include "libavutil/hwcontext_videotoolbox.h" #include "internal.h" #include #include "atsc_a53.h" @@ -226,14 +227,14 @@ typedef struct VTEncContext { int64_t dts_delta; int64_t profile; - int64_t level; - int64_t entropy; - int64_t realtime; - int64_t frames_before; - int64_t frames_after; + int level; + int entropy; + int realtime; + int frames_before; + int frames_after; - int64_t allow_sw; - int64_t require_sw; + int allow_sw; + int require_sw; double alpha_quality; bool flushing; @@ -405,17 +406,43 @@ static int count_nalus(size_t length_code_size, return 0; } -static CMVideoCodecType get_cm_codec_type(enum AVCodecID id, - enum AVPixelFormat fmt, +static CMVideoCodecType get_cm_codec_type(AVCodecContext *avctx, + int64_t profile, double alpha_quality) { - switch (id) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt == AV_PIX_FMT_VIDEOTOOLBOX ? avctx->sw_pix_fmt : avctx->pix_fmt); + switch (avctx->codec_id) { case AV_CODEC_ID_H264: return kCMVideoCodecType_H264; case AV_CODEC_ID_HEVC: - if (fmt == AV_PIX_FMT_BGRA && alpha_quality > 0.0) { + if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpha_quality > 0.0) { return kCMVideoCodecType_HEVCWithAlpha; } return kCMVideoCodecType_HEVC; + case AV_CODEC_ID_PRORES: + switch (profile) { + case FF_PROFILE_PRORES_PROXY: + return MKBETAG('a','p','c','o'); // kCMVideoCodecType_AppleProRes422Proxy + case FF_PROFILE_PRORES_LT: + return MKBETAG('a','p','c','s'); // kCMVideoCodecType_AppleProRes422LT + case FF_PROFILE_PRORES_STANDARD: + return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 + case FF_PROFILE_PRORES_HQ: + return MKBETAG('a','p','c','h'); // kCMVideoCodecType_AppleProRes422HQ + case FF_PROFILE_PRORES_4444: + return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444 + case FF_PROFILE_PRORES_XQ: + return MKBETAG('a','p','4','x'); // kCMVideoCodecType_AppleProRes4444XQ + + default: + av_log(avctx, AV_LOG_ERROR, "Unknown profile ID: %"PRId64", using auto\n", profile); + case FF_PROFILE_UNKNOWN: + if (desc && + ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) || + desc->log2_chroma_w == 0)) + return MKBETAG('a','p','4','h'); // kCMVideoCodecType_AppleProRes4444 + else + return MKBETAG('a','p','c','n'); // kCMVideoCodecType_AppleProRes422 + } default: return 0; } } @@ -548,6 +575,7 @@ static int copy_param_sets( static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer) { + VTEncContext *vtctx = avctx->priv_data; CMVideoFormatDescriptionRef vid_fmt; size_t total_size; int status; @@ -558,23 +586,37 @@ static int set_extradata(AVCodecContext *avctx, CMSampleBufferRef sample_buffer) return AVERROR_EXTERNAL; } - status = get_params_size(avctx, vid_fmt, &total_size); - if (status) { - av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n"); - return status; - } + if (vtctx->get_param_set_func) { + status = get_params_size(avctx, vid_fmt, &total_size); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Could not get parameter sets.\n"); + return status; + } - avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!avctx->extradata) { - return AVERROR(ENOMEM); - } - avctx->extradata_size = total_size; + avctx->extradata = av_mallocz(total_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) { + return AVERROR(ENOMEM); + } + avctx->extradata_size = total_size; - status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size); + status = copy_param_sets(avctx, vid_fmt, avctx->extradata, total_size); - if (status) { - av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n"); - return status; + if (status) { + av_log(avctx, AV_LOG_ERROR, "Could not copy param sets.\n"); + return status; + } + } else { + CFDataRef data = CMFormatDescriptionGetExtension(vid_fmt, kCMFormatDescriptionExtension_VerbatimSampleDescription); + if (data && CFGetTypeID(data) == CFDataGetTypeID()) { + CFIndex size = CFDataGetLength(data); + + avctx->extradata = av_mallocz(size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!avctx->extradata) + return AVERROR(ENOMEM); + avctx->extradata_size = size; + + CFDataGetBytes(data, CFRangeMake(0, size), avctx->extradata); + } } return 0; @@ -797,25 +839,9 @@ static int get_cv_pixel_format(AVCodecContext* avctx, range != AVCOL_RANGE_JPEG; //MPEG range is used when no range is set - if (fmt == AV_PIX_FMT_NV12) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr8BiPlanarFullRange : - kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; - } else if (fmt == AV_PIX_FMT_YUV420P) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr8PlanarFullRange : - kCVPixelFormatType_420YpCbCr8Planar; - } else if (fmt == AV_PIX_FMT_BGRA) { - *av_pixel_format = kCVPixelFormatType_32BGRA; - } else if (fmt == AV_PIX_FMT_P010LE) { - *av_pixel_format = range == AVCOL_RANGE_JPEG ? - kCVPixelFormatType_420YpCbCr10BiPlanarFullRange : - kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange; - } else { - return AVERROR(EINVAL); - } + *av_pixel_format = av_map_videotoolbox_format_from_pixfmt2(fmt, range == AVCOL_RANGE_JPEG); - return 0; + return *av_pixel_format ? 0 : AVERROR(EINVAL); } static void add_color_attr(AVCodecContext *avctx, CFMutableDictionaryRef dict) { @@ -1011,6 +1037,7 @@ static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) { break; case AVCOL_SPC_UNSPECIFIED: + case AVCOL_SPC_RGB: *matrix = NULL; break; @@ -1101,7 +1128,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, kVTCompressionPropertyKey_Quality, quality_num); CFRelease(quality_num); - } else { + } else if (avctx->codec_id != AV_CODEC_ID_PRORES) { bit_rate_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bit_rate); @@ -1188,7 +1215,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (avctx->gop_size > 0) { + if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) { CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &avctx->gop_size); @@ -1337,7 +1364,7 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (!vtctx->has_b_frames) { + if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) { status = VTSessionSetProperty(vtctx->session, kVTCompressionPropertyKey_AllowFrameReordering, kCFBooleanFalse); @@ -1362,10 +1389,10 @@ static int vtenc_create_encoder(AVCodecContext *avctx, } } - if (vtctx->realtime) { + if (vtctx->realtime >= 0) { status = VTSessionSetProperty(vtctx->session, compat_keys.kVTCompressionPropertyKey_RealTime, - kCFBooleanTrue); + vtctx->realtime ? kCFBooleanTrue : kCFBooleanFalse); if (status) { av_log(avctx, AV_LOG_ERROR, "Error setting realtime property: %d\n", status); @@ -1387,16 +1414,24 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) CFMutableDictionaryRef pixel_buffer_info; CMVideoCodecType codec_type; VTEncContext *vtctx = avctx->priv_data; - CFStringRef profile_level; + CFStringRef profile_level = NULL; CFNumberRef gamma_level = NULL; int status; - codec_type = get_cm_codec_type(avctx->codec_id, avctx->pix_fmt, vtctx->alpha_quality); + codec_type = get_cm_codec_type(avctx, vtctx->profile, vtctx->alpha_quality); if (!codec_type) { av_log(avctx, AV_LOG_ERROR, "Error: no mapping for AVCodecID %d\n", avctx->codec_id); return AVERROR(EINVAL); } +#if defined(MAC_OS_X_VERSION_10_9) && !TARGET_OS_IPHONE && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9) + if (avctx->codec_id == AV_CODEC_ID_PRORES) { + if (__builtin_available(macOS 10.10, *)) { + VTRegisterProfessionalVideoWorkflowVideoEncoders(); + } + } +#endif + vtctx->codec_id = avctx->codec_id; if (vtctx->codec_id == AV_CODEC_ID_H264) { @@ -1414,12 +1449,14 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) } if (!get_vt_h264_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); - } else { + } else if (vtctx->codec_id == AV_CODEC_ID_HEVC) { vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; if (!vtctx->get_param_set_func) return AVERROR(EINVAL); if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); // HEVC has b-byramid vtctx->has_b_frames = avctx->max_b_frames > 0 ? 2 : 0; + } else if (vtctx->codec_id == AV_CODEC_ID_PRORES) { + avctx->codec_tag = av_bswap32(codec_type); } enc_info = CFDictionaryCreateMutable( @@ -1950,62 +1987,83 @@ static int vtenc_cm_to_avpacket( CMTime dts; CMVideoFormatDescriptionRef vid_fmt; - vtenc_get_frame_info(sample_buffer, &is_key_frame); - status = get_length_code_size(avctx, sample_buffer, &length_code_size); - if (status) return status; - add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER); + if (vtctx->get_param_set_func) { + status = get_length_code_size(avctx, sample_buffer, &length_code_size); + if (status) return status; - if (add_header) { - vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer); - if (!vid_fmt) { - av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n"); + add_header = is_key_frame && !(avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER); + + if (add_header) { + vid_fmt = CMSampleBufferGetFormatDescription(sample_buffer); + if (!vid_fmt) { + av_log(avctx, AV_LOG_ERROR, "Cannot get format description.\n"); + return AVERROR_EXTERNAL; + } + + int status = get_params_size(avctx, vid_fmt, &header_size); + if (status) return status; + } + + status = count_nalus(length_code_size, sample_buffer, &nalu_count); + if(status) + return status; + + if (sei) { + size_t msg_size = get_sei_msg_bytes(sei, + SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35); + + sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1; + } + + in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer); + out_buf_size = header_size + + in_buf_size + + sei_nalu_size + + nalu_count * ((int)sizeof(start_code) - (int)length_code_size); + + status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0); + if (status < 0) + return status; + + if (add_header) { + status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size); + if(status) return status; + } + + status = copy_replace_length_codes( + avctx, + length_code_size, + sample_buffer, + sei, + pkt->data + header_size, + pkt->size - header_size + ); + + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); + return status; + } + } else { + size_t len; + CMBlockBufferRef buf = CMSampleBufferGetDataBuffer(sample_buffer); + if (!buf) { + av_log(avctx, AV_LOG_ERROR, "Error getting block buffer\n"); return AVERROR_EXTERNAL; } - int status = get_params_size(avctx, vid_fmt, &header_size); - if (status) return status; - } + len = CMBlockBufferGetDataLength(buf); - status = count_nalus(length_code_size, sample_buffer, &nalu_count); - if(status) - return status; + status = ff_get_encode_buffer(avctx, pkt, len, 0); + if (status < 0) + return status; - if (sei) { - size_t msg_size = get_sei_msg_bytes(sei, - SEI_TYPE_USER_DATA_REGISTERED_ITU_T_T35); - - sei_nalu_size = sizeof(start_code) + 1 + msg_size + 1; - } - - in_buf_size = CMSampleBufferGetTotalSampleSize(sample_buffer); - out_buf_size = header_size + - in_buf_size + - sei_nalu_size + - nalu_count * ((int)sizeof(start_code) - (int)length_code_size); - - status = ff_get_encode_buffer(avctx, pkt, out_buf_size, 0); - if (status < 0) - return status; - - if (add_header) { - status = copy_param_sets(avctx, vid_fmt, pkt->data, out_buf_size); - if(status) return status; - } - - status = copy_replace_length_codes( - avctx, - length_code_size, - sample_buffer, - sei, - pkt->data + header_size, - pkt->size - header_size - ); - - if (status) { - av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); - return status; + status = CMBlockBufferCopyDataBytes(buf, 0, len, pkt->data); + if (status) { + av_log(avctx, AV_LOG_ERROR, "Error copying packet data: %d\n", status); + return AVERROR_EXTERNAL; + } } if (is_key_frame) { @@ -2046,6 +2104,7 @@ static int get_cv_pixel_info( size_t *strides, size_t *contiguous_buf_size) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); VTEncContext *vtctx = avctx->priv_data; int av_format = frame->format; int av_color_range = frame->color_range; @@ -2053,6 +2112,9 @@ static int get_cv_pixel_info( int range_guessed; int status; + if (!desc) + return AVERROR(EINVAL); + status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed); if (status) { av_log(avctx, @@ -2077,63 +2139,18 @@ static int get_cv_pixel_info( } } - switch (av_format) { - case AV_PIX_FMT_NV12: - *plane_count = 2; + *plane_count = av_pix_fmt_count_planes(avctx->pix_fmt); - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width; - - widths [1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) & -2; - break; - - case AV_PIX_FMT_YUV420P: - *plane_count = 3; - - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width; - - widths [1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : (avctx->width + 1) / 2; - - widths [2] = (avctx->width + 1) / 2; - heights[2] = (avctx->height + 1) / 2; - strides[2] = frame ? frame->linesize[2] : (avctx->width + 1) / 2; - break; - - case AV_PIX_FMT_BGRA: - *plane_count = 1; - - widths [0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : avctx->width * 4; - break; - - case AV_PIX_FMT_P010LE: - *plane_count = 2; - widths[0] = avctx->width; - heights[0] = avctx->height; - strides[0] = frame ? frame->linesize[0] : (avctx->width * 2 + 63) & -64; - - widths[1] = (avctx->width + 1) / 2; - heights[1] = (avctx->height + 1) / 2; - strides[1] = frame ? frame->linesize[1] : ((avctx->width + 1) / 2 + 63) & -64; - break; - - default: - av_log( - avctx, - AV_LOG_ERROR, - "Could not get frame format info for color %d range %d.\n", - av_format, - av_color_range); - - return AVERROR(EINVAL); + for (i = 0; i < desc->nb_components; i++) { + int p = desc->comp[i].plane; + bool hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA); + bool isAlpha = hasAlpha && (p + 1 == *plane_count); + bool isChroma = (p != 0) && !isAlpha; + int shiftw = isChroma ? desc->log2_chroma_w : 0; + int shifth = isChroma ? desc->log2_chroma_h : 0; + widths[p] = (avctx->width + ((1 << shiftw) >> 1)) >> shiftw; + heights[p] = (avctx->height + ((1 << shifth) >> 1)) >> shifth; + strides[p] = frame->linesize[p]; } *contiguous_buf_size = 0; @@ -2375,6 +2392,7 @@ static int vtenc_send_frame(AVCodecContext *avctx, return status; } +#if CONFIG_ATSC_A53 side_data = av_frame_get_side_data(frame, AV_FRAME_DATA_A53_CC); if (vtctx->a53_cc && side_data && side_data->size) { sei = av_mallocz(sizeof(*sei)); @@ -2389,6 +2407,7 @@ static int vtenc_send_frame(AVCodecContext *avctx, } } } +#endif time = CMTimeMake(frame->pts * avctx->time_base.num, avctx->time_base.den); status = VTCompressionSessionEncodeFrame( @@ -2554,6 +2573,7 @@ static int vtenc_populate_extradata(AVCodecContext *avctx, pe_cleanup: + CVPixelBufferRelease(pix_buf); if(vtctx->session) CFRelease(vtctx->session); @@ -2617,6 +2637,39 @@ static const enum AVPixelFormat hevc_pix_fmts[] = { AV_PIX_FMT_NONE }; +static const enum AVPixelFormat prores_pix_fmts[] = { + AV_PIX_FMT_VIDEOTOOLBOX, + AV_PIX_FMT_YUV420P, +#ifdef kCFCoreFoundationVersionNumber10_7 + AV_PIX_FMT_NV12, + AV_PIX_FMT_AYUV64, +#endif + AV_PIX_FMT_UYVY422, +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P010, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV16, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P210, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P216, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV24, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P410, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P416, +#endif + AV_PIX_FMT_BGRA, + AV_PIX_FMT_NONE +}; + #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM #define COMMON_OPTIONS \ { "allow_sw", "Allow software encoding", OFFSET(allow_sw), AV_OPT_TYPE_BOOL, \ @@ -2624,7 +2677,7 @@ static const enum AVPixelFormat hevc_pix_fmts[] = { { "require_sw", "Require software encoding", OFFSET(require_sw), AV_OPT_TYPE_BOOL, \ { .i64 = 0 }, 0, 1, VE }, \ { "realtime", "Hint that encoding should happen in real-time if not faster (e.g. capturing from camera).", \ - OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ + OFFSET(realtime), AV_OPT_TYPE_BOOL, { .i64 = 0 }, -1, 1, VE }, \ { "frames_before", "Other frames will come before the frames in this session. This helps smooth concatenation issues.", \ OFFSET(frames_before), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, \ { "frames_after", "Other frames will come after the frames in this session. This helps smooth concatenation issues.", \ @@ -2632,7 +2685,7 @@ static const enum AVPixelFormat hevc_pix_fmts[] = { #define OFFSET(x) offsetof(VTEncContext, x) static const AVOption h264_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = H264_PROF_AUTO }, H264_PROF_AUTO, H264_PROF_COUNT, VE, "profile" }, { "baseline", "Baseline Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_BASELINE }, INT_MIN, INT_MAX, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "high", "High Profile", 0, AV_OPT_TYPE_CONST, { .i64 = H264_PROF_HIGH }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2686,7 +2739,7 @@ const AVCodec ff_h264_videotoolbox_encoder = { }; static const AVOption hevc_options[] = { - { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" }, + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = HEVC_PROF_AUTO }, HEVC_PROF_AUTO, HEVC_PROF_COUNT, VE, "profile" }, { "main", "Main Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN }, INT_MIN, INT_MAX, VE, "profile" }, { "main10", "Main10 Profile", 0, AV_OPT_TYPE_CONST, { .i64 = HEVC_PROF_MAIN10 }, INT_MIN, INT_MAX, VE, "profile" }, @@ -2720,3 +2773,42 @@ const AVCodec ff_hevc_videotoolbox_encoder = { FF_CODEC_CAP_INIT_CLEANUP, .wrapper_name = "videotoolbox", }; + +static const AVOption prores_options[] = { + { "profile", "Profile", OFFSET(profile), AV_OPT_TYPE_INT64, { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, FF_PROFILE_PRORES_XQ, VE, "profile" }, + { "auto", "Automatically determine based on input format", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_UNKNOWN }, INT_MIN, INT_MAX, VE, "profile" }, + { "proxy", "ProRes 422 Proxy", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_PROXY }, INT_MIN, INT_MAX, VE, "profile" }, + { "lt", "ProRes 422 LT", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_LT }, INT_MIN, INT_MAX, VE, "profile" }, + { "standard", "ProRes 422", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_STANDARD }, INT_MIN, INT_MAX, VE, "profile" }, + { "hq", "ProRes 422 HQ", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_HQ }, INT_MIN, INT_MAX, VE, "profile" }, + { "4444", "ProRes 4444", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_4444 }, INT_MIN, INT_MAX, VE, "profile" }, + { "xq", "ProRes 4444 XQ", 0, AV_OPT_TYPE_CONST, { .i64 = FF_PROFILE_PRORES_XQ }, INT_MIN, INT_MAX, VE, "profile" }, + + COMMON_OPTIONS + { NULL }, +}; + +static const AVClass prores_videotoolbox_class = { + .class_name = "prores_videotoolbox", + .item_name = av_default_item_name, + .option = prores_options, + .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 | + AV_CODEC_CAP_HARDWARE, + .priv_data_size = sizeof(VTEncContext), + .pix_fmts = prores_pix_fmts, + .init = vtenc_init, + .encode2 = vtenc_frame, + .close = vtenc_close, + .priv_class = &prores_videotoolbox_class, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | + FF_CODEC_CAP_INIT_CLEANUP, + .wrapper_name = "videotoolbox", +}; diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 16726080b3..791e531862 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2685,7 +2685,14 @@ static int vp3_decode_frame(AVCodecContext *avctx, skip_bits(&gb, 4); /* width code */ skip_bits(&gb, 4); /* height code */ if (s->version) { - s->version = get_bits(&gb, 5); + int version = get_bits(&gb, 5); +#if !CONFIG_VP4_DECODER + if (version >= 2) { + av_log(avctx, AV_LOG_ERROR, "This build does not support decoding VP4.\n"); + return AVERROR_DECODER_NOT_FOUND; + } +#endif + s->version = version; if (avctx->frame_number == 0) av_log(s->avctx, AV_LOG_DEBUG, "VP version: %d\n", s->version); @@ -3142,10 +3149,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; } diff --git a/libavcodec/vp8dsp.c b/libavcodec/vp8dsp.c index 4ff63d0784..732a483b62 100644 --- a/libavcodec/vp8dsp.c +++ b/libavcodec/vp8dsp.c @@ -743,5 +743,7 @@ av_cold void ff_vp8dsp_init(VP8DSPContext *dsp) ff_vp8dsp_init_x86(dsp); if (ARCH_MIPS) ff_vp8dsp_init_mips(dsp); + if (ARCH_LOONGARCH) + ff_vp8dsp_init_loongarch(dsp); } #endif /* CONFIG_VP8_DECODER */ diff --git a/libavcodec/vp8dsp.h b/libavcodec/vp8dsp.h index cfe1524b0b..7c6208df39 100644 --- a/libavcodec/vp8dsp.h +++ b/libavcodec/vp8dsp.h @@ -101,6 +101,7 @@ void ff_vp8dsp_init_aarch64(VP8DSPContext *c); void ff_vp8dsp_init_arm(VP8DSPContext *c); void ff_vp8dsp_init_x86(VP8DSPContext *c); void ff_vp8dsp_init_mips(VP8DSPContext *c); +void ff_vp8dsp_init_loongarch(VP8DSPContext *c); #define IS_VP7 1 #define IS_VP8 0 diff --git a/libavcodec/vp9.c b/libavcodec/vp9.c index 8317ac6bd8..24841c5b9f 100644 --- a/libavcodec/vp9.c +++ b/libavcodec/vp9.c @@ -181,7 +181,8 @@ static int update_size(AVCodecContext *avctx, int w, int h) CONFIG_VP9_D3D11VA_HWACCEL * 2 + \ CONFIG_VP9_NVDEC_HWACCEL + \ CONFIG_VP9_VAAPI_HWACCEL + \ - CONFIG_VP9_VDPAU_HWACCEL) + CONFIG_VP9_VDPAU_HWACCEL + \ + CONFIG_VP9_VIDEOTOOLBOX_HWACCEL) enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmtp = pix_fmts; VP9Context *s = avctx->priv_data; uint8_t *p; @@ -212,6 +213,9 @@ static int update_size(AVCodecContext *avctx, int w, int h) #endif #if CONFIG_VP9_VDPAU_HWACCEL *fmtp++ = AV_PIX_FMT_VDPAU; +#endif +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + *fmtp++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif break; case AV_PIX_FMT_YUV420P12: @@ -1893,6 +1897,9 @@ const AVCodec ff_vp9_decoder = { #endif #if CONFIG_VP9_VDPAU_HWACCEL HWACCEL_VDPAU(vp9), +#endif +#if CONFIG_VP9_VIDEOTOOLBOX_HWACCEL + HWACCEL_VIDEOTOOLBOX(vp9), #endif NULL }, diff --git a/libavcodec/vp9dsp.c b/libavcodec/vp9dsp.c index 41b8ad1ad1..82bfe394d1 100644 --- a/libavcodec/vp9dsp.c +++ b/libavcodec/vp9dsp.c @@ -98,4 +98,5 @@ av_cold void ff_vp9dsp_init(VP9DSPContext *dsp, int bpp, int bitexact) 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); } diff --git a/libavcodec/vp9dsp.h b/libavcodec/vp9dsp.h index e2256316a8..700dd72de8 100644 --- a/libavcodec/vp9dsp.h +++ b/libavcodec/vp9dsp.h @@ -132,5 +132,6 @@ void ff_vp9dsp_init_aarch64(VP9DSPContext *dsp, int bpp); void ff_vp9dsp_init_arm(VP9DSPContext *dsp, int bpp); void ff_vp9dsp_init_x86(VP9DSPContext *dsp, int bpp, int bitexact); void ff_vp9dsp_init_mips(VP9DSPContext *dsp, int bpp); +void ff_vp9dsp_init_loongarch(VP9DSPContext *dsp, int bpp); #endif /* AVCODEC_VP9DSP_H */ diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index 12698dc2e8..1d97855e60 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -1,6 +1,7 @@ /* * Westwood Studios VQA Video Decoder - * Copyright (C) 2003 The FFmpeg project + * Copyright (c) 2003 Mike Melanson + * Copyright (c) 2021 Pekka Väänänen * * This file is part of FFmpeg. * @@ -61,6 +62,11 @@ * together and the 8-bit pieces together. If most of the vectors are * clustered into one group of 256 vectors, most of the 4-bit index pieces * should be the same. + * + * VQA3 introduces a 15-bit high color codebook, delta coding, replaces + * the above "split byte" scheme with RLE compression, and extends the + * "format80" compression with relative references. In VQA3 the whole + * codebook is always updated as a whole without splitting it into pieces. */ #include @@ -81,7 +87,7 @@ #define MAX_CODEBOOK_VECTORS 0xFF00 #define SOLID_PIXEL_VECTORS 0x100 #define MAX_VECTORS (MAX_CODEBOOK_VECTORS + SOLID_PIXEL_VECTORS) -#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4) +#define MAX_CODEBOOK_SIZE (MAX_VECTORS * 4 * 4 * sizeof(uint16_t)) #define CBF0_TAG MKBETAG('C', 'B', 'F', '0') #define CBFZ_TAG MKBETAG('C', 'B', 'F', 'Z') @@ -90,9 +96,11 @@ #define CPL0_TAG MKBETAG('C', 'P', 'L', '0') #define CPLZ_TAG MKBETAG('C', 'P', 'L', 'Z') #define VPTZ_TAG MKBETAG('V', 'P', 'T', 'Z') +#define VPTR_TAG MKBETAG('V', 'P', 'T', 'R') +#define VPRZ_TAG MKBETAG('V', 'P', 'R', 'Z') typedef struct VqaContext { - + AVFrame *frame; AVCodecContext *avctx; GetByteContext gb; @@ -104,9 +112,9 @@ typedef struct VqaContext { int vector_height; /* height of individual vector */ int vqa_version; /* this should be either 1, 2 or 3 */ - unsigned char *codebook; /* the current codebook */ + unsigned char *codebook; /* the current codebook */ int codebook_size; - unsigned char *next_codebook_buffer; /* accumulator for next codebook */ + unsigned char *next_codebook_buffer; /* accumulator for next codebook */ int next_codebook_buffer_index; unsigned char *decode_buffer; @@ -115,16 +123,15 @@ typedef struct VqaContext { /* number of frames to go before replacing codebook */ int partial_countdown; int partial_count; - } VqaContext; static av_cold int vqa_decode_init(AVCodecContext *avctx) { VqaContext *s = avctx->priv_data; int i, j, codebook_index, ret; + int colors; s->avctx = avctx; - avctx->pix_fmt = AV_PIX_FMT_PAL8; /* make sure the extradata made it */ if (s->avctx->extradata_size != VQA_HEADER_SIZE) { @@ -134,17 +141,12 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) /* load up the VQA parameters from the header */ s->vqa_version = s->avctx->extradata[0]; - switch (s->vqa_version) { - case 1: - case 2: - break; - case 3: - avpriv_report_missing_feature(avctx, "VQA Version %d", s->vqa_version); - return AVERROR_PATCHWELCOME; - default: + + if (s->vqa_version < 1 || s->vqa_version > 3) { avpriv_request_sample(avctx, "VQA Version %i", s->vqa_version); - return AVERROR_PATCHWELCOME; + return AVERROR_INVALIDDATA; } + s->width = AV_RL16(&s->avctx->extradata[6]); s->height = AV_RL16(&s->avctx->extradata[8]); if ((ret = ff_set_dimensions(avctx, s->width, s->height)) < 0) { @@ -155,6 +157,14 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) s->vector_height = s->avctx->extradata[11]; s->partial_count = s->partial_countdown = s->avctx->extradata[13]; + colors = (s->avctx->extradata[14] << 8) | s->avctx->extradata[15]; + + if (colors > 0) { + avctx->pix_fmt = AV_PIX_FMT_PAL8; + } else { + avctx->pix_fmt = AV_PIX_FMT_RGB555LE; + } + /* the vector dimensions have to meet very stringent requirements */ if ((s->vector_width != 4) || ((s->vector_height != 2) && (s->vector_height != 4))) { @@ -167,6 +177,10 @@ static av_cold int vqa_decode_init(AVCodecContext *avctx) return AVERROR_INVALIDDATA; } + s->frame = av_frame_alloc(); + if (!s->frame) + return AVERROR(ENOMEM); + /* allocate codebooks */ s->codebook_size = MAX_CODEBOOK_SIZE; s->codebook = av_malloc(s->codebook_size); @@ -225,6 +239,7 @@ static int decode_format80(VqaContext *s, int src_size, int src_pos; unsigned char color; int i; + int relative = 0; if (src_size < 0 || src_size > bytestream2_get_bytes_left(&s->gb)) { av_log(s->avctx, AV_LOG_ERROR, "Chunk size %d is out of range\n", @@ -232,6 +247,13 @@ static int decode_format80(VqaContext *s, int src_size, return AVERROR_INVALIDDATA; } + /* the "new" scheme makes references relative to destination pointer */ + if (bytestream2_peek_byte(&s->gb) == 0x00) { + relative = 1; + bytestream2_get_byte(&s->gb); + ff_tlog(s->avctx, "found new format stream "); + } + start = bytestream2_tell(&s->gb); while (bytestream2_tell(&s->gb) - start < src_size) { opcode = bytestream2_get_byte(&s->gb); @@ -251,7 +273,9 @@ static int decode_format80(VqaContext *s, int src_size, count = bytestream2_get_le16(&s->gb); src_pos = bytestream2_get_le16(&s->gb); - ff_tlog(s->avctx, "(1) copy %X bytes from absolute pos %X\n", count, src_pos); + if (relative) + src_pos = dest_index - src_pos; + ff_tlog(s->avctx, "(1) copy %X bytes from pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -271,7 +295,9 @@ static int decode_format80(VqaContext *s, int src_size, count = (opcode & 0x3F) + 3; src_pos = bytestream2_get_le16(&s->gb); - ff_tlog(s->avctx, "(3) copy %X bytes from absolute pos %X\n", count, src_pos); + if (relative) + src_pos = dest_index - src_pos; + ff_tlog(s->avctx, "(3) copy %X bytes from pos %X\n", count, src_pos); CHECK_COUNT(); CHECK_COPY(src_pos); for (i = 0; i < count; i++) @@ -313,7 +339,7 @@ static int decode_format80(VqaContext *s, int src_size, return 0; // let's display what we decoded anyway } -static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) +static int vqa_decode_frame_pal8(VqaContext *s, AVFrame *frame) { unsigned int chunk_type; unsigned int chunk_size; @@ -512,9 +538,8 @@ static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) break; case 3: -/* not implemented yet */ - lines = 0; - break; + av_log(s->avctx, AV_LOG_ERROR, "VQA3 shouldn't have a color palette"); + return AVERROR_INVALIDDATA; } while (lines--) { @@ -583,13 +608,185 @@ static int vqa_decode_chunk(VqaContext *s, AVFrame *frame) if (s->partial_countdown <= 0) { bytestream2_init(&s->gb, s->next_codebook_buffer, s->next_codebook_buffer_index); /* decompress codebook */ - if ((res = decode_format80(s, s->next_codebook_buffer_index, - s->codebook, s->codebook_size, 0)) < 0) - return res; + res = decode_format80(s, s->next_codebook_buffer_index, + s->codebook, s->codebook_size, 0); /* reset accounting */ s->next_codebook_buffer_index = 0; s->partial_countdown = s->partial_count; + if (res < 0) + return res; + } + } + + return 0; +} + +static int vqa_decode_frame_hicolor(VqaContext *s, AVFrame *frame) +{ + unsigned int chunk_type; + unsigned int chunk_size; + unsigned int index = 0; + int res; + + int cbf0_chunk = -1; + int cbfz_chunk = -1; + int vptr_chunk = -1; + int vprz_chunk = -1; + + GetByteContext gb_stream; + + while (bytestream2_get_bytes_left(&s->gb) >= 8) { + chunk_type = bytestream2_get_be32u(&s->gb); + index = bytestream2_tell(&s->gb); + chunk_size = bytestream2_get_be32u(&s->gb); + + switch (chunk_type) { + case CBF0_TAG: + cbf0_chunk = index; + break; + case CBFZ_TAG: + cbfz_chunk = index; + break; + case VPTR_TAG: + vptr_chunk = index; + break; + case VPRZ_TAG: + vprz_chunk = index; + break; + default: + av_log(s->avctx, AV_LOG_ERROR, "Found unknown chunk type: %s (%08X)\n", + av_fourcc2str(av_bswap32(chunk_type)), chunk_type); + break; + } + + bytestream2_skip(&s->gb, chunk_size + (chunk_size & 0x01)); + } + + /* next, look for a full codebook */ + if ((cbf0_chunk != -1) && (cbfz_chunk != -1)) { + /* a chunk should not have both chunk types */ + av_log(s->avctx, AV_LOG_ERROR, "problem: found both CBF0 and CBFZ chunks\n"); + return AVERROR_INVALIDDATA; + } + + /* decompress the full codebook chunk */ + if (cbfz_chunk != -1) { + bytestream2_seek(&s->gb, cbfz_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, s->codebook, + s->codebook_size, 0)) < 0) + return res; + } + + /* copy a full codebook */ + if (cbf0_chunk != -1) { + bytestream2_seek(&s->gb, cbf0_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + /* sanity check the full codebook size */ + if (chunk_size > MAX_CODEBOOK_SIZE) { + av_log(s->avctx, AV_LOG_ERROR, "problem: CBF0 chunk too large (0x%X bytes)\n", + chunk_size); + return AVERROR_INVALIDDATA; + } + + bytestream2_get_buffer(&s->gb, s->codebook, chunk_size); + } + + /* decode the frame */ + + if (vptr_chunk != -1) { + /* copy uncompressed tile data */ + bytestream2_seek(&s->gb, vptr_chunk, SEEK_SET); + chunk_size = bytestream2_get_be32(&s->gb); + if (chunk_size > s->decode_buffer_size) { + av_log(s->avctx, AV_LOG_ERROR, "VPTR chunk didn't fit in decode buffer"); + return AVERROR_INVALIDDATA; + } + bytestream2_get_buffer(&s->gb, s->decode_buffer, chunk_size); + } else if (vprz_chunk != -1) { + /* decompress the tile data */ + bytestream2_seek(&s->gb, vprz_chunk, SEEK_SET); + + chunk_size = bytestream2_get_be32(&s->gb); + if ((res = decode_format80(s, chunk_size, s->decode_buffer, s->decode_buffer_size, 0)) < 0) + return res; + } else { + av_log(s->avctx, AV_LOG_ERROR, "frame has no block data\n"); + return AVERROR_INVALIDDATA; + } + + /* now uncompress the per-row RLE of the decode buffer and draw the blocks in framebuffer */ + + bytestream2_init(&gb_stream, s->decode_buffer, s->decode_buffer_size); + + for (int y_pos = 0; y_pos < s->height; y_pos += s->vector_height) { + int x_pos = 0; + + while (x_pos < s->width) { + int vector_index = 0; + int count = 0; + uint16_t code; + int type; + + if (bytestream2_get_bytes_left(&gb_stream) < 2) + return AVERROR_INVALIDDATA; + + code = bytestream2_get_le16(&gb_stream); + + type = code >> 13; + code &= 0x1fff; + + if (type == 0) { + x_pos += 4 * code; + continue; + } else if (type < 3) { + vector_index = code & 0xff; + count = ((code & 0x1f00) >> 7) + 1 + type; + } else if (type < 5) { + vector_index = code; + count = 1; + } else if (type < 7) { + vector_index = code; + count = bytestream2_get_byte(&gb_stream); + } else { + av_log(s->avctx, AV_LOG_ERROR, " unknown type in VPTR chunk (%d)\n",type); + return AVERROR_INVALIDDATA; + } + + if (count < 0 || count > (s->width - x_pos) / s->vector_width) { + av_log(s->avctx, AV_LOG_ERROR, "invalid count: %d\n", count); + return AVERROR_INVALIDDATA; + } + + while (count-- && x_pos < s->width) { + const int bytes_per_vector = 4 * s->vector_height * sizeof(uint16_t); + unsigned char *src = s->codebook + vector_index * bytes_per_vector; + unsigned char *dst = s->frame->data[0] + y_pos * s->frame->linesize[0] + + sizeof(uint16_t) * x_pos; + + if (vector_index >= MAX_VECTORS) + return AVERROR_INVALIDDATA; + + for (int y = 0; y < s->vector_height; y++) { + int size = 4 * sizeof(uint16_t); + memcpy(dst, src, size); + dst += s->frame->linesize[0]; + src += size; + } + + /* we might want to read the next block index from stream */ + if ((type == 2) && count > 0) { + vector_index = bytestream2_get_byte(&gb_stream); + } + + x_pos += 4; + } + + if (count > 0) { + av_log(s->avctx, AV_LOG_ERROR, "had %d leftover vectors\n", count); + return AVERROR_BUG; + } } } @@ -601,19 +798,30 @@ static int vqa_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { VqaContext *s = avctx->priv_data; - AVFrame *frame = data; int res; - if ((res = ff_get_buffer(avctx, frame, 0)) < 0) + if ((res = ff_reget_buffer(avctx, s->frame, 0)) < 0) return res; bytestream2_init(&s->gb, avpkt->data, avpkt->size); - if ((res = vqa_decode_chunk(s, frame)) < 0) - return res; - /* make the palette available on the way out */ - memcpy(frame->data[1], s->palette, PALETTE_COUNT * 4); - frame->palette_has_changed = 1; + if (avctx->pix_fmt == AV_PIX_FMT_PAL8) { + if ((res = vqa_decode_frame_pal8(s, s->frame)) < 0) + return res; + + /* make the palette available on the way out */ + memcpy(s->frame->data[1], s->palette, PALETTE_COUNT * 4); + s->frame->palette_has_changed = 1; + } else if (avctx->pix_fmt == AV_PIX_FMT_RGB555LE) { + if ((res = vqa_decode_frame_hicolor(s, s->frame)) < 0) + return res; + } else { + av_log(s->avctx, AV_LOG_ERROR, "unsupported pixel format\n"); + return AVERROR_BUG; + } + + if ((res = av_frame_ref(data, s->frame)) < 0) + return res; *got_frame = 1; @@ -625,6 +833,7 @@ static av_cold int vqa_decode_end(AVCodecContext *avctx) { VqaContext *s = avctx->priv_data; + av_frame_free(&s->frame); av_freep(&s->codebook); av_freep(&s->next_codebook_buffer); av_freep(&s->decode_buffer); @@ -633,7 +842,7 @@ static av_cold int vqa_decode_end(AVCodecContext *avctx) } static const AVCodecDefault vqa_defaults[] = { - { "max_pixels", "320*240" }, + { "max_pixels", "640*480" }, { NULL }, }; diff --git a/libavcodec/vt_internal.h b/libavcodec/vt_internal.h index fb64735b8c..54a11fd1b5 100644 --- a/libavcodec/vt_internal.h +++ b/libavcodec/vt_internal.h @@ -19,6 +19,9 @@ #ifndef AVCODEC_VT_INTERNAL_H #define AVCODEC_VT_INTERNAL_H +#include "avcodec.h" +#include "videotoolbox.h" + typedef struct VTContext { // The current bitstream buffer. uint8_t *bitstream; @@ -45,6 +48,12 @@ typedef struct VTContext { } VTContext; int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame); +int ff_videotoolbox_common_init(AVCodecContext *avctx); +int ff_videotoolbox_frame_params(AVCodecContext *avctx, + AVBufferRef *hw_frames_ctx); +int ff_videotoolbox_buffer_copy(VTContext *vtctx, + const uint8_t *buffer, + uint32_t size); int ff_videotoolbox_uninit(AVCodecContext *avctx); int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, const uint8_t *buffer, @@ -52,7 +61,9 @@ int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx, int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size); +int ff_videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame); CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx); CFDataRef ff_videotoolbox_hvcc_extradata_create(AVCodecContext *avctx); +CFDataRef ff_videotoolbox_vpcc_extradata_create(AVCodecContext *avctx); #endif /* AVCODEC_VT_INTERNAL_H */ diff --git a/libavcodec/wmv2.c b/libavcodec/wmv2.c index 327c5bdae1..fd64a0938f 100644 --- a/libavcodec/wmv2.c +++ b/libavcodec/wmv2.c @@ -23,7 +23,6 @@ #include "mpegutils.h" #include "mpegvideo.h" #include "msmpeg4data.h" -#include "simple_idct.h" #include "wmv2.h" #include "wmv2data.h" @@ -54,49 +53,6 @@ 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], diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index c500e3e779..f7745c5a83 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -27,9 +27,53 @@ #include "mpegvideo.h" #include "msmpeg4.h" #include "msmpeg4data.h" +#include "simple_idct.h" #include "wmv2.h" +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); +} + static int parse_mb_skip(Wmv2Context *w) { int mb_x, mb_y; diff --git a/libavcodec/x86/h264_qpel.c b/libavcodec/x86/h264_qpel.c index a2d8a64976..320d98933a 100644 --- a/libavcodec/x86/h264_qpel.c +++ b/libavcodec/x86/h264_qpel.c @@ -338,7 +338,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc21_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src, halfHV, stride, SIZE);\ }\ @@ -348,7 +348,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc23_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## h264_qpel ## SIZE ## _h_lowpass_l2_ ## MMX(dst, src+stride, halfHV, stride, SIZE);\ }\ @@ -358,7 +358,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc12_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+2, halfHV, stride, SIZE, SIZE);\ }\ @@ -368,7 +368,7 @@ static void OPNAME ## h264_qpel ## SIZE ## _mc32_ ## MMX(uint8_t *dst, const uin LOCAL_ALIGNED(ALIGN, uint8_t, temp, [SIZE*(SIZE<8?12:24)*2 + SIZE*SIZE]);\ uint8_t * const halfHV= temp;\ int16_t * const halfV= (int16_t*)(temp + SIZE*SIZE);\ - av_assert2(((int)temp & 7) == 0);\ + av_assert2(((uintptr_t)temp & 7) == 0);\ ff_put_h264_qpel ## SIZE ## _hv_lowpass_ ## MMX(halfHV, halfV, src, SIZE, SIZE, stride);\ ff_ ## OPNAME ## pixels ## SIZE ## _l2_shift5_mmxext(dst, halfV+3, halfHV, stride, SIZE, SIZE);\ }\ diff --git a/libavcodec/x86/me_cmp_init.c b/libavcodec/x86/me_cmp_init.c index 701eb1ab25..9af911bb88 100644 --- a/libavcodec/x86/me_cmp_init.c +++ b/libavcodec/x86/me_cmp_init.c @@ -131,7 +131,7 @@ static int vsad_intra16_mmx(MpegEncContext *v, uint8_t *pix, uint8_t *dummy, { int tmp; - av_assert2((((int) pix) & 7) == 0); + av_assert2(((uintptr_t) pix & 7) == 0); av_assert2((stride & 7) == 0); #define SUM(in0, in1, out0, out1) \ @@ -195,8 +195,8 @@ static int vsad16_mmx(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2, { int tmp; - av_assert2((((int) pix1) & 7) == 0); - av_assert2((((int) pix2) & 7) == 0); + 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) \ diff --git a/libavcodec/x86/mpegvideoenc_template.c b/libavcodec/x86/mpegvideoenc_template.c index b32b1b0350..30c06a6b2c 100644 --- a/libavcodec/x86/mpegvideoenc_template.c +++ b/libavcodec/x86/mpegvideoenc_template.c @@ -109,7 +109,7 @@ static int RENAME(dct_quantize)(MpegEncContext *s, const uint16_t *qmat, *bias; LOCAL_ALIGNED_16(int16_t, temp_block, [64]); - av_assert2((7&(int)(&temp_block[0])) == 0); //did gcc align it correctly? + av_assert2((7&(uintptr_t)(&temp_block[0])) == 0); //did gcc align it correctly? //s->fdct (block); RENAME_FDCT(ff_fdct)(block); // cannot be anything else ... diff --git a/libavcodec/xsubdec.c b/libavcodec/xsubdec.c index 979399bae6..85cd7d1c20 100644 --- a/libavcodec/xsubdec.c +++ b/libavcodec/xsubdec.c @@ -52,6 +52,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, 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; int w, h, x, y, i, ret; @@ -100,47 +101,40 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_sub_ptr, if (!sub->rects) return AVERROR(ENOMEM); - sub->rects[0] = av_mallocz(sizeof(*sub->rects[0])); - if (!sub->rects[0]) { - av_freep(&sub->rects); + sub->rects[0] = rect = av_mallocz(sizeof(*sub->rects[0])); + if (!sub->rects[0]) return AVERROR(ENOMEM); - } - sub->rects[0]->x = x; sub->rects[0]->y = y; - sub->rects[0]->w = w; sub->rects[0]->h = h; - sub->rects[0]->type = SUBTITLE_BITMAP; - sub->rects[0]->linesize[0] = w; - sub->rects[0]->data[0] = av_malloc(w * h); - sub->rects[0]->nb_colors = 4; - sub->rects[0]->data[1] = av_mallocz(AVPALETTE_SIZE); - if (!sub->rects[0]->data[0] || !sub->rects[0]->data[1]) { - av_freep(&sub->rects[0]->data[1]); - av_freep(&sub->rects[0]->data[0]); - av_freep(&sub->rects[0]); - av_freep(&sub->rects); - return AVERROR(ENOMEM); - } sub->num_rects = 1; + rect->x = x; rect->y = y; + rect->w = w; rect->h = h; + rect->type = SUBTITLE_BITMAP; + rect->linesize[0] = w; + rect->data[0] = av_malloc(w * h); + rect->nb_colors = 4; + rect->data[1] = av_mallocz(AVPALETTE_SIZE); + if (!rect->data[0] || !rect->data[1]) + return AVERROR(ENOMEM); // read palette - for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t*)sub->rects[0]->data[1])[i] = bytestream_get_be24(&buf); + for (i = 0; i < rect->nb_colors; i++) + ((uint32_t*)rect->data[1])[i] = bytestream_get_be24(&buf); if (!has_alpha) { // make all except background (first entry) non-transparent - for (i = 1; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->data[1])[i] |= 0xff000000; + for (i = 1; i < rect->nb_colors; i++) + ((uint32_t *)rect->data[1])[i] |= 0xff000000; } else { - for (i = 0; i < sub->rects[0]->nb_colors; i++) - ((uint32_t *)sub->rects[0]->data[1])[i] |= (unsigned)*buf++ << 24; + for (i = 0; i < rect->nb_colors; i++) + ((uint32_t *)rect->data[1])[i] |= (unsigned)*buf++ << 24; } // process RLE-compressed data if ((ret = init_get_bits8(&gb, buf, buf_end - buf)) < 0) return ret; - bitmap = sub->rects[0]->data[0]; + bitmap = rect->data[0]; for (y = 0; y < h; y++) { // interlaced: do odd lines - if (y == (h + 1) / 2) bitmap = sub->rects[0]->data[0] + w; + if (y == (h + 1) / 2) bitmap = rect->data[0] + w; for (x = 0; x < w; ) { int log2 = ff_log2_tab[show_bits(&gb, 8)]; int run = get_bits(&gb, 14 - 4 * (log2 >> 1)); diff --git a/libavdevice/Makefile b/libavdevice/Makefile index 0dfe47a1f4..53efda0514 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -9,7 +9,6 @@ OBJS = alldevices.o \ utils.o \ OBJS-$(HAVE_LIBC_MSVCRT) += file_open.o -OBJS-$(CONFIG_SHARED) += reverse.o # input/output devices OBJS-$(CONFIG_ALSA_INDEV) += alsa_dec.o alsa.o timefilter.o @@ -54,6 +53,9 @@ OBJS-$(CONFIG_XV_OUTDEV) += xv.o OBJS-$(CONFIG_LIBCDIO_INDEV) += libcdio.o OBJS-$(CONFIG_LIBDC1394_INDEV) += libdc1394.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS-$(CONFIG_DECKLINK_INDEV) += reverse.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avdeviceres.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index fbbe187a51..22323a0a44 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -18,8 +18,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" -#include "libavutil/thread.h" #include "libavformat/internal.h" #include "avdevice.h" diff --git a/libavdevice/avdevice.c b/libavdevice/avdevice.c index 2ae26ab8e3..8f460c7564 100644 --- a/libavdevice/avdevice.c +++ b/libavdevice/avdevice.c @@ -157,6 +157,7 @@ void avdevice_free_list_devices(AVDeviceInfoList **device_list) if (dev) { av_freep(&dev->device_name); av_freep(&dev->device_description); + av_freep(&dev->media_types); av_free(dev); } } diff --git a/libavdevice/avdevice.h b/libavdevice/avdevice.h index 8370bbc7f2..6f24976dcc 100644 --- a/libavdevice/avdevice.h +++ b/libavdevice/avdevice.h @@ -457,6 +457,8 @@ void avdevice_capabilities_free(AVDeviceCapabilitiesQuery **caps, AVFormatContex typedef struct AVDeviceInfo { char *device_name; /**< device name, format depends on device */ char *device_description; /**< human friendly name */ + enum AVMediaType *media_types; /**< array indicating what media types(s), if any, a device can provide. If null, cannot provide any */ + int nb_media_types; /**< length of media_types array, 0 if device cannot provide any media types */ } AVDeviceInfo; /** diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 5b11dcd46d..79d6ac5b38 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -29,6 +29,9 @@ #define IDeckLinkProfileAttributes IDeckLinkAttributes #endif +extern "C" { +#include "libavcodec/packet_internal.h" +} #include "libavutil/thread.h" #include "decklink_common_c.h" #if CONFIG_LIBKLVANC @@ -75,7 +78,7 @@ class decklink_output_callback; class decklink_input_callback; typedef struct AVPacketQueue { - PacketList *first_pkt, *last_pkt; + PacketList pkt_list; int nb_packets; unsigned long long size; int abort_request; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 491fe4be3d..c97a72d93d 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -483,16 +483,16 @@ static void avpacket_queue_init(AVFormatContext *avctx, AVPacketQueue *q) static void avpacket_queue_flush(AVPacketQueue *q) { - PacketList *pkt, *pkt1; + PacketListEntry *pkt, *pkt1; pthread_mutex_lock(&q->mutex); - for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { + for (pkt = q->pkt_list.head; pkt != NULL; pkt = pkt1) { pkt1 = pkt->next; av_packet_unref(&pkt->pkt); av_freep(&pkt); } - q->last_pkt = NULL; - q->first_pkt = NULL; + q->pkt_list.head = NULL; + q->pkt_list.tail = NULL; q->nb_packets = 0; q->size = 0; pthread_mutex_unlock(&q->mutex); @@ -516,7 +516,7 @@ static unsigned long long avpacket_queue_size(AVPacketQueue *q) static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) { - PacketList *pkt1; + PacketListEntry *pkt1; // Drop Packet if queue size is > maximum queue size if (avpacket_queue_size(q) > (uint64_t)q->max_q_size) { @@ -530,7 +530,7 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) return -1; } - pkt1 = (PacketList *)av_malloc(sizeof(PacketList)); + pkt1 = (PacketListEntry *)av_malloc(sizeof(*pkt1)); if (!pkt1) { av_packet_unref(pkt); return -1; @@ -540,13 +540,13 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) pthread_mutex_lock(&q->mutex); - if (!q->last_pkt) { - q->first_pkt = pkt1; + if (!q->pkt_list.tail) { + q->pkt_list.head = pkt1; } else { - q->last_pkt->next = pkt1; + q->pkt_list.tail->next = pkt1; } - q->last_pkt = pkt1; + q->pkt_list.tail = pkt1; q->nb_packets++; q->size += pkt1->pkt.size + sizeof(*pkt1); @@ -558,17 +558,16 @@ static int avpacket_queue_put(AVPacketQueue *q, AVPacket *pkt) static int avpacket_queue_get(AVPacketQueue *q, AVPacket *pkt, int block) { - PacketList *pkt1; int ret; pthread_mutex_lock(&q->mutex); for (;; ) { - pkt1 = q->first_pkt; + PacketListEntry *pkt1 = q->pkt_list.head; if (pkt1) { - q->first_pkt = pkt1->next; - if (!q->first_pkt) { - q->last_pkt = NULL; + q->pkt_list.head = pkt1->next; + if (!q->pkt_list.head) { + q->pkt_list.tail = NULL; } q->nb_packets--; q->size -= pkt1->pkt.size + sizeof(*pkt1); diff --git a/libavdevice/dshow.c b/libavdevice/dshow.c index 8d0a6fcc09..3a16f3720f 100644 --- a/libavdevice/dshow.c +++ b/libavdevice/dshow.c @@ -23,12 +23,37 @@ #include "libavutil/parseutils.h" #include "libavutil/pixdesc.h" #include "libavutil/opt.h" +#include "libavutil/mem.h" #include "libavformat/internal.h" #include "libavformat/riff.h" #include "avdevice.h" #include "libavcodec/raw.h" #include "objidl.h" #include "shlwapi.h" +// NB: technically, we should include dxva.h and use +// DXVA_ExtendedFormat, but that type is not defined in +// the MinGW headers. The DXVA2_ExtendedFormat and the +// contents of its fields is identical to +// DXVA_ExtendedFormat (see https://docs.microsoft.com/en-us/windows/win32/medfound/extended-color-information#color-space-in-media-types) +// and is provided by MinGW as well, so we use that +// instead. NB also that per the Microsoft docs, the +// lowest 8 bits of the structure, i.e. the SampleFormat +// field, contain AMCONTROL_xxx flags instead of sample +// format information, and should thus not be used. +// NB further that various values in the structure's +// fields (e.g. BT.2020 color space) are not provided +// for either of the DXVA structs, but are provided in +// the flags of the corresponding fields of Media Foundation. +// These may be provided by DirectShow devices (e.g. LAVFilters +// does so). So we use those values here too (the equivalence is +// indicated by Microsoft example code: https://docs.microsoft.com/en-us/windows/win32/api/dxva2api/ns-dxva2api-dxva2_videodesc) +#include "d3d9types.h" +#include "dxva2api.h" + +#ifndef AMCONTROL_COLORINFO_PRESENT +// not defined in some versions of MinGW's dvdmedia.h +# define AMCONTROL_COLORINFO_PRESENT 0x00000080 // if set, indicates DXVA color info is present in the upper (24) bits of the dwControlFlags +#endif static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) @@ -51,14 +76,169 @@ static enum AVPixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount) return AV_PIX_FMT_0RGB32; } } - return avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), biCompression); // all others + return avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, biCompression); // all others +} + +static enum AVColorRange dshow_color_range(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->NominalRange) + { + case DXVA2_NominalRange_Unknown: + return AVCOL_RANGE_UNSPECIFIED; + case DXVA2_NominalRange_Normal: // equal to DXVA2_NominalRange_0_255 + return AVCOL_RANGE_JPEG; + case DXVA2_NominalRange_Wide: // equal to DXVA2_NominalRange_16_235 + return AVCOL_RANGE_MPEG; + case DXVA2_NominalRange_48_208: + // not an ffmpeg color range + return AVCOL_RANGE_UNSPECIFIED; + + // values from MediaFoundation SDK (mfobjects.h) + case 4: // MFNominalRange_64_127 + // not an ffmpeg color range + return AVCOL_RANGE_UNSPECIFIED; + + default: + return AVCOL_RANGE_UNSPECIFIED; + } +} + +static enum AVColorSpace dshow_color_space(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoTransferMatrix) + { + case DXVA2_VideoTransferMatrix_BT709: + return AVCOL_SPC_BT709; + case DXVA2_VideoTransferMatrix_BT601: + return AVCOL_SPC_BT470BG; + case DXVA2_VideoTransferMatrix_SMPTE240M: + return AVCOL_SPC_SMPTE240M; + + // values from MediaFoundation SDK (mfobjects.h) + case 4: // MFVideoTransferMatrix_BT2020_10 + case 5: // MFVideoTransferMatrix_BT2020_12 + if (fmt_info->VideoTransferFunction == 12) // MFVideoTransFunc_2020_const + return AVCOL_SPC_BT2020_CL; + else + return AVCOL_SPC_BT2020_NCL; + + default: + return AVCOL_SPC_UNSPECIFIED; + } +} + +static enum AVColorPrimaries dshow_color_primaries(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoPrimaries) + { + case DXVA2_VideoPrimaries_Unknown: + return AVCOL_PRI_UNSPECIFIED; + case DXVA2_VideoPrimaries_reserved: + return AVCOL_PRI_RESERVED; + case DXVA2_VideoPrimaries_BT709: + return AVCOL_PRI_BT709; + case DXVA2_VideoPrimaries_BT470_2_SysM: + return AVCOL_PRI_BT470M; + case DXVA2_VideoPrimaries_BT470_2_SysBG: + case DXVA2_VideoPrimaries_EBU3213: // this is PAL + return AVCOL_PRI_BT470BG; + case DXVA2_VideoPrimaries_SMPTE170M: + case DXVA2_VideoPrimaries_SMPTE_C: + return AVCOL_PRI_SMPTE170M; + case DXVA2_VideoPrimaries_SMPTE240M: + return AVCOL_PRI_SMPTE240M; + + // values from MediaFoundation SDK (mfobjects.h) + case 9: // MFVideoPrimaries_BT2020 + return AVCOL_PRI_BT2020; + case 10: // MFVideoPrimaries_XYZ + return AVCOL_PRI_SMPTE428; + case 11: // MFVideoPrimaries_DCI_P3 + return AVCOL_PRI_SMPTE431; + case 12: // MFVideoPrimaries_ACES (Academy Color Encoding System) + // not an FFmpeg color primary + return AVCOL_PRI_UNSPECIFIED; + + default: + return AVCOL_PRI_UNSPECIFIED; + } +} + +static enum AVColorTransferCharacteristic dshow_color_trc(DXVA2_ExtendedFormat *fmt_info) +{ + switch (fmt_info->VideoTransferFunction) + { + case DXVA2_VideoTransFunc_Unknown: + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_10: + return AVCOL_TRC_LINEAR; + case DXVA2_VideoTransFunc_18: + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_20: + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case DXVA2_VideoTransFunc_22: + return AVCOL_TRC_GAMMA22; + case DXVA2_VideoTransFunc_709: + return AVCOL_TRC_BT709; + case DXVA2_VideoTransFunc_240M: + return AVCOL_TRC_SMPTE240M; + case DXVA2_VideoTransFunc_sRGB: + return AVCOL_TRC_IEC61966_2_1; + case DXVA2_VideoTransFunc_28: + return AVCOL_TRC_GAMMA28; + + // values from MediaFoundation SDK (mfobjects.h) + case 9: // MFVideoTransFunc_Log_100 + return AVCOL_TRC_LOG; + case 10: // MFVideoTransFunc_Log_316 + return AVCOL_TRC_LOG_SQRT; + case 11: // MFVideoTransFunc_709_sym + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case 12: // MFVideoTransFunc_2020_const + case 13: // MFVideoTransFunc_2020 + if (fmt_info->VideoTransferMatrix == 5) // MFVideoTransferMatrix_BT2020_12 + return AVCOL_TRC_BT2020_12; + else + return AVCOL_TRC_BT2020_10; + case 14: // MFVideoTransFunc_26 + // not an FFmpeg transfer characteristic + return AVCOL_TRC_UNSPECIFIED; + case 15: // MFVideoTransFunc_2084 + return AVCOL_TRC_SMPTEST2084; + case 16: // MFVideoTransFunc_HLG + return AVCOL_TRC_ARIB_STD_B67; + case 17: // MFVideoTransFunc_10_rel + // not an FFmpeg transfer characteristic? Undocumented also by MS + return AVCOL_TRC_UNSPECIFIED; + + default: + return AVCOL_TRC_UNSPECIFIED; + } +} + +static enum AVChromaLocation dshow_chroma_loc(DXVA2_ExtendedFormat *fmt_info) +{ + if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_Cosited) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_Cosited | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes) + return AVCHROMA_LOC_TOPLEFT; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_MPEG1) // that is: DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes + return AVCHROMA_LOC_CENTER; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_MPEG2) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_AlignedChromaPlanes) + return AVCHROMA_LOC_LEFT; + else if (fmt_info->VideoChromaSubsampling == DXVA2_VideoChromaSubsampling_DV_PAL) // that is: (DXVA2_VideoChromaSubsampling_Horizontally_Cosited | DXVA2_VideoChromaSubsampling_Vertically_Cosited) + return AVCHROMA_LOC_TOPLEFT; + else + // unknown + return AVCHROMA_LOC_UNSPECIFIED; } static int dshow_read_close(AVFormatContext *s) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if (ctx->control) { IMediaControl_Stop(ctx->control); @@ -118,7 +298,7 @@ dshow_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -162,7 +342,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e { AVFormatContext *s = priv_data; struct dshow_ctx *ctx = s->priv_data; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; // dump_videohdr(s, vdhdr); @@ -171,7 +351,7 @@ callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, e if(shall_we_drop(s, index, devtype)) goto fail; - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -197,16 +377,92 @@ fail: return; } +static void +dshow_get_device_media_types(AVFormatContext *avctx, enum dshowDeviceType devtype, + enum dshowSourceFilterType sourcetype, IBaseFilter *device_filter, + enum AVMediaType **media_types, int *nb_media_types) +{ + IEnumPins *pins = 0; + IPin *pin; + int has_audio = 0, has_video = 0; + + if (IBaseFilter_EnumPins(device_filter, &pins) != S_OK) + return; + + while (IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { + IKsPropertySet *p = NULL; + PIN_INFO info = { 0 }; + GUID category; + DWORD r2; + IEnumMediaTypes *types = NULL; + AM_MEDIA_TYPE *type; + + if (IPin_QueryPinInfo(pin, &info) != S_OK) + goto next; + IBaseFilter_Release(info.pFilter); + + if (info.dir != PINDIR_OUTPUT) + goto next; + if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK) + goto next; + if (IKsPropertySet_Get(p, &ROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, + NULL, 0, &category, sizeof(GUID), &r2) != S_OK) + goto next; + if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE)) + goto next; + + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + goto next; + + // enumerate media types exposed by pin + // NB: don't know if a pin can expose both audio and video, check 'm all to be safe + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { + if (IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) { + has_video = 1; + } else if (IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) { + has_audio = 1; + } + CoTaskMemFree(type); + } + + next: + if (types) + IEnumMediaTypes_Release(types); + if (p) + IKsPropertySet_Release(p); + if (pin) + IPin_Release(pin); + } + + IEnumPins_Release(pins); + + if (has_audio || has_video) { + int nb_types = has_audio + has_video; + *media_types = av_malloc_array(nb_types, sizeof(enum AVMediaType)); + if (*media_types) { + if (has_audio) + (*media_types)[0] = AVMEDIA_TYPE_AUDIO; + if (has_video) + (*media_types)[0 + has_audio] = AVMEDIA_TYPE_VIDEO; + *nb_media_types = nb_types; + } + } +} + /** * Cycle through available devices using the device enumerator devenum, * retrieve the device with type specified by devtype and return the * pointer to the object found in *pfilter. * If pfilter is NULL, list all device names. + * If device_list is not NULL, populate it with found devices instead of + * outputting device names to log */ static int dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, enum dshowDeviceType devtype, enum dshowSourceFilterType sourcetype, - IBaseFilter **pfilter, char **device_unique_name) + IBaseFilter **pfilter, char **device_unique_name, + AVDeviceInfoList **device_list) { struct dshow_ctx *ctx = avctx->priv_data; IBaseFilter *device_filter = NULL; @@ -238,18 +494,21 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, IBindCtx *bind_ctx = NULL; LPOLESTR olestr = NULL; LPMALLOC co_malloc = NULL; + AVDeviceInfo *device = NULL; + enum AVMediaType *media_types = NULL; + int nb_media_types = 0; int i; r = CoGetMalloc(1, &co_malloc); if (r != S_OK) - goto fail1; + goto fail; r = CreateBindCtx(0, &bind_ctx); if (r != S_OK) - goto fail1; + goto fail; /* GetDisplayname works for both video and audio, DevicePath doesn't */ r = IMoniker_GetDisplayName(m, bind_ctx, NULL, &olestr); if (r != S_OK) - goto fail1; + goto fail; unique_name = dup_wchar_to_utf8(olestr); /* replace ':' with '_' since we use : to delineate between sources */ for (i = 0; i < strlen(unique_name); i++) { @@ -259,34 +518,88 @@ dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum, r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag); if (r != S_OK) - goto fail1; + goto fail; var.vt = VT_BSTR; r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL); if (r != S_OK) - goto fail1; + goto fail; friendly_name = dup_wchar_to_utf8(var.bstrVal); if (pfilter) { if (strcmp(device_name, friendly_name) && strcmp(device_name, unique_name)) - goto fail1; + goto fail; if (!skip--) { r = IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter); if (r != S_OK) { av_log(avctx, AV_LOG_ERROR, "Unable to BindToObject for %s\n", device_name); - goto fail1; + goto fail; } *device_unique_name = unique_name; unique_name = NULL; // success, loop will end now } } else { - av_log(avctx, AV_LOG_INFO, " \"%s\"\n", friendly_name); - av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); + // get media types exposed by pins of device + if (IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void* ) &device_filter) == S_OK) { + dshow_get_device_media_types(avctx, devtype, sourcetype, device_filter, &media_types, &nb_media_types); + IBaseFilter_Release(device_filter); + device_filter = NULL; + } + if (device_list) { + device = av_mallocz(sizeof(AVDeviceInfo)); + if (!device) + goto fail; + + device->device_name = av_strdup(friendly_name); + device->device_description = av_strdup(unique_name); + if (!device->device_name || !device->device_description) + goto fail; + + // make space in device_list for this new device + if (av_reallocp_array(&(*device_list)->devices, + (*device_list)->nb_devices + 1, + sizeof(*(*device_list)->devices)) < 0) + goto fail; + + // attach media_types to device + device->nb_media_types = nb_media_types; + device->media_types = media_types; + nb_media_types = 0; + media_types = NULL; + + // store device in list + (*device_list)->devices[(*device_list)->nb_devices] = device; + (*device_list)->nb_devices++; + device = NULL; // copied into array, make sure not freed below + } + else { + av_log(avctx, AV_LOG_INFO, "\"%s\"", friendly_name); + if (nb_media_types > 0) { + const char* media_type = av_get_media_type_string(media_types[0]); + av_log(avctx, AV_LOG_INFO, " (%s", media_type ? media_type : "unknown"); + for (int i = 1; i < nb_media_types; ++i) { + media_type = av_get_media_type_string(media_types[i]); + av_log(avctx, AV_LOG_INFO, ", %s", media_type ? media_type : "unknown"); + } + av_log(avctx, AV_LOG_INFO, ")"); + } else { + av_log(avctx, AV_LOG_INFO, " (none)"); + } + av_log(avctx, AV_LOG_INFO, "\n"); + av_log(avctx, AV_LOG_INFO, " Alternative name \"%s\"\n", unique_name); + } } -fail1: + fail: + av_freep(&media_types); + if (device) { + av_freep(&device->device_name); + av_freep(&device->device_description); + // NB: no need to av_freep(&device->media_types), its only moved to device once nothing can fail anymore + av_free(device); + } if (olestr && co_malloc) IMalloc_Free(co_malloc, olestr); if (bind_ctx) @@ -312,9 +625,168 @@ fail1: return 0; } +static int dshow_get_device_list(AVFormatContext *avctx, AVDeviceInfoList *device_list) +{ + ICreateDevEnum *devenum = NULL; + int r; + int ret = AVERROR(EIO); + + if (!device_list) + return AVERROR(EINVAL); + + CoInitialize(0); + + r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, + &IID_ICreateDevEnum, (void**)&devenum); + if (r != S_OK) { + av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n"); + goto error; + } + + ret = dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, &device_list); + if (ret < S_OK) + goto error; + ret = dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, &device_list); + +error: + if (devenum) + ICreateDevEnum_Release(devenum); + + CoUninitialize(); + + return ret; +} + +static int dshow_should_set_format(AVFormatContext *avctx, enum dshowDeviceType devtype) +{ + struct dshow_ctx *ctx = avctx->priv_data; + + return (devtype == VideoDevice && (ctx->framerate || + (ctx->requested_width && ctx->requested_height) || + ctx->pixel_format != AV_PIX_FMT_NONE || + ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) + || (devtype == AudioDevice && (ctx->channels || ctx->sample_size || ctx->sample_rate)); +} + + +struct dshow_format_info { + enum dshowDeviceType devtype; + // video + int64_t framerate; + enum AVPixelFormat pix_fmt; + enum AVCodecID codec_id; + enum AVColorRange col_range; + enum AVColorSpace col_space; + enum AVColorPrimaries col_prim; + enum AVColorTransferCharacteristic col_trc; + enum AVChromaLocation chroma_loc; + int width; + int height; + // audio + int sample_rate; + int sample_size; + int channels; +}; + +// user must av_free the returned pointer +static struct dshow_format_info *dshow_get_format_info(AM_MEDIA_TYPE *type) +{ + struct dshow_format_info *fmt_info = NULL; + BITMAPINFOHEADER *bih; + DXVA2_ExtendedFormat *extended_format_info = NULL; + WAVEFORMATEX *fx; + enum dshowDeviceType devtype; + int64_t framerate; + + if (!type) + return NULL; + + if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { + VIDEOINFOHEADER *v = (void *) type->pbFormat; + framerate = v->AvgTimePerFrame; + bih = &v->bmiHeader; + devtype = VideoDevice; + } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { + VIDEOINFOHEADER2 *v = (void *) type->pbFormat; + devtype = VideoDevice; + framerate = v->AvgTimePerFrame; + bih = &v->bmiHeader; + if (v->dwControlFlags & AMCONTROL_COLORINFO_PRESENT) + extended_format_info = (DXVA2_ExtendedFormat *) &v->dwControlFlags; + } else if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) { + fx = (void *) type->pbFormat; + devtype = AudioDevice; + } else { + return NULL; + } + + fmt_info = av_mallocz(sizeof(struct dshow_format_info)); + if (!fmt_info) + return NULL; + // initialize fields where unset is not zero + fmt_info->pix_fmt = AV_PIX_FMT_NONE; + fmt_info->col_space = AVCOL_SPC_UNSPECIFIED; + fmt_info->col_prim = AVCOL_PRI_UNSPECIFIED; + fmt_info->col_trc = AVCOL_TRC_UNSPECIFIED; + // now get info about format + fmt_info->devtype = devtype; + if (devtype == VideoDevice) { + fmt_info->width = bih->biWidth; + fmt_info->height = bih->biHeight; + fmt_info->framerate = framerate; + fmt_info->pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); + if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { + const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; + fmt_info->codec_id = av_codec_get_id(tags, bih->biCompression); + } + else + fmt_info->codec_id = AV_CODEC_ID_RAWVIDEO; + + if (extended_format_info) { + fmt_info->col_range = dshow_color_range(extended_format_info); + fmt_info->col_space = dshow_color_space(extended_format_info); + fmt_info->col_prim = dshow_color_primaries(extended_format_info); + fmt_info->col_trc = dshow_color_trc(extended_format_info); + fmt_info->chroma_loc = dshow_chroma_loc(extended_format_info); + } + } else { + fmt_info->sample_rate = fx->nSamplesPerSec; + fmt_info->sample_size = fx->wBitsPerSample; + fmt_info->channels = fx->nChannels; + } + + return fmt_info; +} + +static void dshow_get_default_format(IPin *pin, IAMStreamConfig *config, enum dshowDeviceType devtype, AM_MEDIA_TYPE **type) +{ + HRESULT hr; + + if ((hr = IAMStreamConfig_GetFormat(config, type)) != S_OK) { + if (hr == E_NOTIMPL || !IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + // default not available or of wrong type, + // fall back to iterating exposed formats + // until one of the right type is found + IEnumMediaTypes* types = NULL; + if (IPin_EnumMediaTypes(pin, &types) != S_OK) + return; + IEnumMediaTypes_Reset(types); + while (IEnumMediaTypes_Next(types, 1, type, NULL) == S_OK) { + if (IsEqualGUID(&(*type)->majortype, devtype == VideoDevice ? &MEDIATYPE_Video : &MEDIATYPE_Audio)) { + break; + } + CoTaskMemFree(*type); + *type = NULL; + } + IEnumMediaTypes_Release(types); + } + } +} + /** - * Cycle through available formats using the specified pin, - * try to set parameters specified through AVOptions and if successful + * Cycle through available formats available from the specified pin, + * try to set parameters specified through AVOptions, or the pin's + * default format if no such parameters were set. If successful, * return 1 in *pformat_set. * If pformat_set is NULL, list all pin capabilities. */ @@ -325,9 +797,27 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, struct dshow_ctx *ctx = avctx->priv_data; IAMStreamConfig *config = NULL; AM_MEDIA_TYPE *type = NULL; + AM_MEDIA_TYPE *previous_match_type = NULL; int format_set = 0; void *caps = NULL; int i, n, size, r; + int wait_for_better = 0; + int use_default; + + // format parameters requested by user + // if none are requested by user, the values will below be set to + // those of the default format + // video + enum AVCodecID requested_video_codec_id = ctx->video_codec_id; + enum AVPixelFormat requested_pixel_format = ctx->pixel_format; + int64_t requested_framerate = ctx->framerate ? ((int64_t)ctx->requested_framerate.den * 10000000) + / ctx->requested_framerate.num : 0; + int requested_width = ctx->requested_width; + int requested_height = ctx->requested_height; + // audio + int requested_sample_rate = ctx->sample_rate; + int requested_sample_size = ctx->sample_size; + int requested_channels = ctx->channels; if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK) return; @@ -338,7 +828,62 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, if (!caps) goto end; + /** + * If we should open the device with the default format, + * then: + * 1. check what the format of the default device is, and + * 2. below we iterate all formats till we find a matching + * one, with most info exposed (see comment below). + */ + use_default = !dshow_should_set_format(avctx, devtype); + if (use_default && pformat_set) + { + // get default + dshow_get_default_format(pin, config, devtype, &type); + if (!type) + // this pin does not expose any formats of the expected type + goto end; + + if (type) { + // interrogate default format, so we know what to search for below + struct dshow_format_info *fmt_info = dshow_get_format_info(type); + if (fmt_info) { + if (fmt_info->devtype == VideoDevice) { + requested_video_codec_id = fmt_info->codec_id; + requested_pixel_format = fmt_info->pix_fmt; + requested_framerate = fmt_info->framerate; + requested_width = fmt_info->width; + requested_height = fmt_info->height; + } else { + requested_sample_rate = fmt_info->sample_rate; + requested_sample_size = fmt_info->sample_size; + requested_channels = fmt_info->channels; + } + av_free(fmt_info); // free but don't set to NULL to enable below check + } + + if (type && type->pbFormat) + CoTaskMemFree(type->pbFormat); + CoTaskMemFree(type); + type = NULL; + if (!fmt_info) + // default format somehow invalid, can't continue with this pin + goto end; + fmt_info = NULL; + } + } + + // NB: some devices (e.g. Logitech C920) expose each video format twice: + // both a format containing a VIDEOINFOHEADER and a format containing + // a VIDEOINFOHEADER2. We want, if possible, to select a format with a + // VIDEOINFOHEADER2, as this potentially provides more info about the + // format. So, if in the iteration below we have found a matching format, + // but it is a VIDEOINFOHEADER, keep looking for a matching format that + // exposes contains a VIDEOINFOHEADER2. Fall back to the VIDEOINFOHEADER + // format if no corresponding VIDEOINFOHEADER2 is found when we finish + // iterating. for (i = 0; i < n && !format_set; i++) { + struct dshow_format_info *fmt_info = NULL; r = IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps); if (r != S_OK) goto next; @@ -346,73 +891,100 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, ff_print_AM_MEDIA_TYPE(type); #endif + fmt_info = dshow_get_format_info(type); + if (!fmt_info) + goto next; + if (devtype == VideoDevice) { VIDEO_STREAM_CONFIG_CAPS *vcaps = caps; BITMAPINFOHEADER *bih; int64_t *fr; - const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; #if DSHOWDEBUG ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps); #endif + + if (fmt_info->devtype != VideoDevice) + goto next; + if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) { VIDEOINFOHEADER *v = (void *) type->pbFormat; - fr = &v->AvgTimePerFrame; + fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; + wait_for_better = 1; } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) { VIDEOINFOHEADER2 *v = (void *) type->pbFormat; - fr = &v->AvgTimePerFrame; + fr = &v->AvgTimePerFrame; bih = &v->bmiHeader; - } else { - goto next; + wait_for_better = 0; } + if (!pformat_set) { - enum AVPixelFormat pix_fmt = dshow_pixfmt(bih->biCompression, bih->biBitCount); - if (pix_fmt == AV_PIX_FMT_NONE) { - enum AVCodecID codec_id = av_codec_get_id(tags, bih->biCompression); - const AVCodec *codec = avcodec_find_decoder(codec_id); - if (codec_id == AV_CODEC_ID_NONE || !codec) { + const char *chroma = av_chroma_location_name(fmt_info->chroma_loc); + if (fmt_info->pix_fmt == AV_PIX_FMT_NONE) { + const AVCodec *codec = avcodec_find_decoder(fmt_info->codec_id); + if (fmt_info->codec_id == AV_CODEC_ID_NONE || !codec) { av_log(avctx, AV_LOG_INFO, " unknown compression type 0x%X", (int) bih->biCompression); } else { av_log(avctx, AV_LOG_INFO, " vcodec=%s", codec->name); } } else { - av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(pix_fmt)); + av_log(avctx, AV_LOG_INFO, " pixel_format=%s", av_get_pix_fmt_name(fmt_info->pix_fmt)); } - av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n", + av_log(avctx, AV_LOG_INFO, " min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g", vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy, 1e7 / vcaps->MaxFrameInterval, vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy, 1e7 / vcaps->MinFrameInterval); - continue; - } - if (ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO) { - if (ctx->video_codec_id != av_codec_get_id(tags, bih->biCompression)) - goto next; - } - if (ctx->pixel_format != AV_PIX_FMT_NONE && - ctx->pixel_format != dshow_pixfmt(bih->biCompression, bih->biBitCount)) { + + if (fmt_info->col_range != AVCOL_RANGE_UNSPECIFIED || + fmt_info->col_space != AVCOL_SPC_UNSPECIFIED || + fmt_info->col_prim != AVCOL_PRI_UNSPECIFIED || + fmt_info->col_trc != AVCOL_TRC_UNSPECIFIED) { + const char *range = av_color_range_name(fmt_info->col_range); + const char *space = av_color_space_name(fmt_info->col_space); + const char *prim = av_color_primaries_name(fmt_info->col_prim); + const char *trc = av_color_transfer_name(fmt_info->col_trc); + av_log(avctx, AV_LOG_INFO, " (%s, %s/%s/%s", + range ? range : "unknown", + space ? space : "unknown", + prim ? prim : "unknown", + trc ? trc : "unknown"); + if (fmt_info->chroma_loc != AVCHROMA_LOC_UNSPECIFIED) + av_log(avctx, AV_LOG_INFO, ", %s", chroma ? chroma : "unknown"); + av_log(avctx, AV_LOG_INFO, ")"); + } + else if (fmt_info->chroma_loc != AVCHROMA_LOC_UNSPECIFIED) + av_log(avctx, AV_LOG_INFO, "(%s)", chroma ? chroma : "unknown"); + + av_log(avctx, AV_LOG_INFO, "\n"); goto next; } - if (ctx->framerate) { - int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000) - / ctx->requested_framerate.num; - if (framerate > vcaps->MaxFrameInterval || - framerate < vcaps->MinFrameInterval) + if (requested_video_codec_id != AV_CODEC_ID_RAWVIDEO) { + if (requested_video_codec_id != fmt_info->codec_id) goto next; - *fr = framerate; } - if (ctx->requested_width && ctx->requested_height) { - if (ctx->requested_width > vcaps->MaxOutputSize.cx || - ctx->requested_width < vcaps->MinOutputSize.cx || - ctx->requested_height > vcaps->MaxOutputSize.cy || - ctx->requested_height < vcaps->MinOutputSize.cy) + if (requested_pixel_format != AV_PIX_FMT_NONE && + requested_pixel_format != fmt_info->pix_fmt) { + goto next; + } + if (requested_framerate) { + if (requested_framerate > vcaps->MaxFrameInterval || + requested_framerate < vcaps->MinFrameInterval) goto next; - bih->biWidth = ctx->requested_width; - bih->biHeight = ctx->requested_height; + *fr = requested_framerate; + } + if (requested_width && requested_height) { + if (requested_width > vcaps->MaxOutputSize.cx || + requested_width < vcaps->MinOutputSize.cx || + requested_height > vcaps->MaxOutputSize.cy || + requested_height < vcaps->MinOutputSize.cy) + goto next; + bih->biWidth = requested_width; + bih->biHeight = requested_height; } } else { - AUDIO_STREAM_CONFIG_CAPS *acaps = caps; WAVEFORMATEX *fx; + AUDIO_STREAM_CONFIG_CAPS *acaps = caps; #if DSHOWDEBUG ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps); #endif @@ -422,39 +994,87 @@ dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype, goto next; } if (!pformat_set) { - av_log(avctx, AV_LOG_INFO, " min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n", - acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency, - acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency); + av_log( + avctx, + AV_LOG_INFO, + " ch=%2u, bits=%2u, rate=%6lu\n", + fx->nChannels, fx->wBitsPerSample, fx->nSamplesPerSec + ); continue; } - if (ctx->sample_rate) { - if (ctx->sample_rate > acaps->MaximumSampleFrequency || - ctx->sample_rate < acaps->MinimumSampleFrequency) + if (requested_sample_rate) { + if (requested_sample_rate > acaps->MaximumSampleFrequency || + requested_sample_rate < acaps->MinimumSampleFrequency) goto next; - fx->nSamplesPerSec = ctx->sample_rate; + fx->nSamplesPerSec = requested_sample_rate; } - if (ctx->sample_size) { - if (ctx->sample_size > acaps->MaximumBitsPerSample || - ctx->sample_size < acaps->MinimumBitsPerSample) + if (requested_sample_size) { + if (requested_sample_size > acaps->MaximumBitsPerSample || + requested_sample_size < acaps->MinimumBitsPerSample) goto next; - fx->wBitsPerSample = ctx->sample_size; + fx->wBitsPerSample = requested_sample_size; } - if (ctx->channels) { - if (ctx->channels > acaps->MaximumChannels || - ctx->channels < acaps->MinimumChannels) + if (requested_channels) { + if (requested_channels > acaps->MaximumChannels || + requested_channels < acaps->MinimumChannels) goto next; - fx->nChannels = ctx->channels; + fx->nChannels = requested_channels; } } - if (IAMStreamConfig_SetFormat(config, type) != S_OK) - goto next; - format_set = 1; + + // found a matching format. Either apply or store + // for safekeeping if we might maybe find a better + // format with more info attached to it (see comment + // above loop) + if (!wait_for_better) { + if (IAMStreamConfig_SetFormat(config, type) != S_OK) + goto next; + format_set = 1; + } + else if (!previous_match_type) { + // store this matching format for possible later use. + // If we have already found a matching format, ignore it + previous_match_type = type; + type = NULL; + } next: - if (type->pbFormat) + av_freep(&fmt_info); + if (type && type->pbFormat) CoTaskMemFree(type->pbFormat); CoTaskMemFree(type); + type = NULL; } + + // set the pin's format, if wanted + if (pformat_set && !format_set) { + if (previous_match_type) { + // previously found a matching VIDEOINFOHEADER format and stored + // it for safe keeping. Searching further for a matching + // VIDEOINFOHEADER2 format yielded nothing. So set the pin's + // format based on the VIDEOINFOHEADER format. + // NB: this never applies to an audio format because + // previous_match_type always NULL in that case + if (IAMStreamConfig_SetFormat(config, previous_match_type) == S_OK) + format_set = 1; + } + else if (use_default) { + // default format returned by device apparently was not contained + // in the capabilities of any of the formats returned by the device + // (sic?). Fall back to directly setting the default format + dshow_get_default_format(pin, config, devtype, &type); + if (IAMStreamConfig_SetFormat(config, type) == S_OK) + format_set = 1; + if (type && type->pbFormat) + CoTaskMemFree(type->pbFormat); + CoTaskMemFree(type); + type = NULL; + } + } + end: + if (previous_match_type && previous_match_type->pbFormat) + CoTaskMemFree(previous_match_type->pbFormat); + CoTaskMemFree(previous_match_type); IAMStreamConfig_Release(config); av_free(caps); if (pformat_set) @@ -569,15 +1189,10 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, IPin *pin; int r; - const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio }; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio only"; const char *sourcetypename = (sourcetype == VideoSourceDevice) ? "video" : "audio"; - int set_format = (devtype == VideoDevice && (ctx->framerate || - (ctx->requested_width && ctx->requested_height) || - ctx->pixel_format != AV_PIX_FMT_NONE || - ctx->video_codec_id != AV_CODEC_ID_RAWVIDEO)) - || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate)); + int set_format = dshow_should_set_format(avctx, devtype); int format_set = 0; int should_show_properties = (devtype == VideoDevice) ? ctx->show_video_device_dialog : ctx->show_audio_device_dialog; @@ -597,9 +1212,7 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) { IKsPropertySet *p = NULL; - IEnumMediaTypes *types = NULL; PIN_INFO info = {0}; - AM_MEDIA_TYPE *type; GUID category; DWORD r2; char *name_buf = NULL; @@ -642,35 +1255,24 @@ dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype, } } - if (set_format) { - dshow_cycle_formats(avctx, devtype, pin, &format_set); - if (!format_set) { - goto next; - } + // will either try to find format matching options supplied by user + // or try to open default format. Successful if returns with format_set==1 + dshow_cycle_formats(avctx, devtype, pin, &format_set); + if (!format_set) { + goto next; } + if (devtype == AudioDevice && ctx->audio_buffer_size) { if (dshow_set_audio_buffer_size(avctx, pin) < 0) { av_log(avctx, AV_LOG_ERROR, "unable to set audio buffer size %d to pin, using pin anyway...", ctx->audio_buffer_size); } } - if (IPin_EnumMediaTypes(pin, &types) != S_OK) - goto next; - - IEnumMediaTypes_Reset(types); - /* in case format_set was not called, just verify the majortype */ - while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) { - if (IsEqualGUID(&type->majortype, mediatype[devtype])) { - device_pin = pin; - av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename); - goto next; - } - CoTaskMemFree(type); + if (format_set) { + device_pin = pin; + av_log(avctx, AV_LOG_DEBUG, "Selecting pin %s on %s\n", name_buf, devtypename); } - next: - if (types) - IEnumMediaTypes_Release(types); if (p) IKsPropertySet_Release(p); if (device_pin != pin) @@ -713,12 +1315,12 @@ dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum, char *device_unique_name = NULL; int r; - if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name)) < 0) + if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_unique_name, NULL)) < 0) return r; ctx->device_filter[devtype] = device_filter; + ctx->device_unique_name[devtype] = device_unique_name; if ((r = dshow_cycle_pins(avctx, devtype, sourcetype, device_filter, NULL)) < 0) return r; - av_freep(&device_unique_name); return 0; } @@ -773,7 +1375,7 @@ dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum, av_log(avctx, AV_LOG_INFO, "Capture filter loaded successfully from file \"%s\".\n", filename); } else { - if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name)) < 0) { + if ((r = dshow_cycle_devices(avctx, devenum, devtype, sourcetype, &device_filter, &device_filter_unique_name, NULL)) < 0) { ret = r; goto error; } @@ -940,6 +1542,7 @@ dshow_add_device(AVFormatContext *avctx, AM_MEDIA_TYPE type; AVCodecParameters *par; AVStream *st; + struct dshow_format_info *fmt_info = NULL; int ret = AVERROR(EIO); type.pbFormat = NULL; @@ -954,6 +1557,11 @@ dshow_add_device(AVFormatContext *avctx, ctx->capture_filter[devtype]->stream_index = st->index; ff_dshow_pin_ConnectionMediaType(ctx->capture_pin[devtype], &type); + fmt_info = dshow_get_format_info(&type); + if (!fmt_info) { + ret = AVERROR(EIO); + goto error; + } par = st->codecpar; if (devtype == VideoDevice) { @@ -978,26 +1586,21 @@ dshow_add_device(AVFormatContext *avctx, st->r_frame_rate = av_inv_q(time_base); par->codec_type = AVMEDIA_TYPE_VIDEO; - par->width = bih->biWidth; - par->height = bih->biHeight; + par->width = fmt_info->width; + par->height = fmt_info->height; par->codec_tag = bih->biCompression; - par->format = dshow_pixfmt(bih->biCompression, bih->biBitCount); + par->format = fmt_info->pix_fmt; if (bih->biCompression == MKTAG('H', 'D', 'Y', 'C')) { av_log(avctx, AV_LOG_DEBUG, "attempt to use full range for HDYC...\n"); par->color_range = AVCOL_RANGE_MPEG; // just in case it needs this... } - if (par->format == AV_PIX_FMT_NONE) { - const AVCodecTag *const tags[] = { avformat_get_riff_video_tags(), NULL }; - par->codec_id = av_codec_get_id(tags, bih->biCompression); - if (par->codec_id == AV_CODEC_ID_NONE) { - av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " - "Please report type 0x%X.\n", (int) bih->biCompression); - ret = AVERROR_PATCHWELCOME; - goto error; - } - par->bits_per_coded_sample = bih->biBitCount; - } else { - par->codec_id = AV_CODEC_ID_RAWVIDEO; + par->color_range = fmt_info->col_range; + par->color_space = fmt_info->col_space; + par->color_primaries = fmt_info->col_prim; + par->color_trc = fmt_info->col_trc; + par->chroma_location = fmt_info->chroma_loc; + par->codec_id = fmt_info->codec_id; + if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) { par->bits_per_coded_sample = bih->biBitCount; if (par->height < 0) { @@ -1010,23 +1613,26 @@ dshow_add_device(AVFormatContext *avctx, } } } + } else { + if (par->codec_id == AV_CODEC_ID_NONE) { + av_log(avctx, AV_LOG_ERROR, "Unknown compression type. " + "Please report type 0x%X.\n", (int) bih->biCompression); + ret = AVERROR_PATCHWELCOME; + goto error; + } + par->bits_per_coded_sample = bih->biBitCount; } } else { - WAVEFORMATEX *fx = NULL; - - if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { - fx = (void *) type.pbFormat; - } - if (!fx) { + if (!IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) { av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n"); goto error; } par->codec_type = AVMEDIA_TYPE_AUDIO; - par->format = sample_fmt_bits_per_sample(fx->wBitsPerSample); + par->format = sample_fmt_bits_per_sample(fmt_info->sample_size); par->codec_id = waveform_codec_id(par->format); - par->sample_rate = fx->nSamplesPerSec; - par->channels = fx->nChannels; + par->sample_rate = fmt_info->sample_rate; + par->channels = fmt_info->channels; } avpriv_set_pts_info(st, 64, 1, 10000000); @@ -1034,6 +1640,7 @@ dshow_add_device(AVFormatContext *avctx, ret = 0; error: + av_freep(&fmt_info); if (type.pbFormat) CoTaskMemFree(type.pbFormat); return ret; @@ -1129,10 +1736,8 @@ static int dshow_read_header(AVFormatContext *avctx) } if (ctx->list_devices) { - av_log(avctx, AV_LOG_INFO, "DirectShow video devices (some may be both video and audio devices)\n"); - dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL); - av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n"); - dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL); + dshow_cycle_devices(avctx, devenum, VideoDevice, VideoSourceDevice, NULL, NULL, NULL); + dshow_cycle_devices(avctx, devenum, AudioDevice, AudioSourceDevice, NULL, NULL, NULL); ret = AVERROR_EXIT; goto error; } @@ -1151,6 +1756,7 @@ static int dshow_read_header(AVFormatContext *avctx) } } } + // don't exit yet, allow it to list crossbar options in dshow_open_device } if (ctx->device_name[VideoDevice]) { if ((r = dshow_open_device(avctx, devenum, VideoDevice, VideoSourceDevice)) < 0 || @@ -1262,7 +1868,7 @@ static int dshow_check_event_queue(IMediaEvent *media_event) static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt) { struct dshow_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while (!ctx->eof && !pktl) { WaitForSingleObject(ctx->mutex, INFINITE); @@ -1317,6 +1923,7 @@ static const AVOption options[] = { { "audio_device_save", "save audio capture filter device (and properties) to file", OFFSET(audio_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_load", "load video capture filter device (and properties) from file", OFFSET(video_filter_load_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, { "video_device_save", "save video capture filter device (and properties) to file", OFFSET(video_filter_save_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, + { "use_video_device_timestamps", "use device instead of wallclock timestamps for video frames", OFFSET(use_video_device_timestamps), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DEC }, { NULL }, }; @@ -1335,6 +1942,7 @@ const AVInputFormat ff_dshow_demuxer = { .read_header = dshow_read_header, .read_packet = dshow_read_packet, .read_close = dshow_read_close, - .flags = AVFMT_NOFILE, + .get_device_list= dshow_get_device_list, + .flags = AVFMT_NOFILE | AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK, .priv_class = &dshow_class, }; diff --git a/libavdevice/dshow_capture.h b/libavdevice/dshow_capture.h index 06ded2ba96..b548cd7afc 100644 --- a/libavdevice/dshow_capture.h +++ b/libavdevice/dshow_capture.h @@ -70,7 +70,7 @@ enum dshowSourceFilterType { }; #define DECLARE_QUERYINTERFACE(prefix, class, ...) \ -long \ +long WINAPI \ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObject) \ { \ struct GUIDoffset ifaces[] = __VA_ARGS__; \ @@ -93,14 +93,14 @@ ff_dshow_##prefix##_QueryInterface(class *this, const GUID *riid, void **ppvObje return E_NOINTERFACE; \ } #define DECLARE_ADDREF(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_AddRef(class *this) \ { \ dshowdebug("ff_dshow_"AV_STRINGIFY(prefix)"_AddRef(%p)\t%ld\n", this, this->ref+1); \ return InterlockedIncrement(&this->ref); \ } #define DECLARE_RELEASE(prefix, class) \ -unsigned long \ +unsigned long WINAPI \ ff_dshow_##prefix##_Release(class *this) \ { \ long ref = InterlockedDecrement(&this->ref); \ @@ -167,34 +167,34 @@ struct DShowPin { IMemInputPinVtbl *imemvtbl; }; -long ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); -unsigned long ff_dshow_pin_AddRef (DShowPin *); -unsigned long ff_dshow_pin_Release (DShowPin *); -long ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_Disconnect (DShowPin *); -long ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); -long ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); -long ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); -long ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); -long ff_dshow_pin_QueryId (DShowPin *, wchar_t **); -long ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); -long ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); -long ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); -long ff_dshow_pin_EndOfStream (DShowPin *); -long ff_dshow_pin_BeginFlush (DShowPin *); -long ff_dshow_pin_EndFlush (DShowPin *); -long ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); +long WINAPI ff_dshow_pin_QueryInterface (DShowPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_pin_AddRef (DShowPin *); +unsigned long WINAPI ff_dshow_pin_Release (DShowPin *); +long WINAPI ff_dshow_pin_Connect (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_ReceiveConnection (DShowPin *, IPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_Disconnect (DShowPin *); +long WINAPI ff_dshow_pin_ConnectedTo (DShowPin *, IPin **); +long WINAPI ff_dshow_pin_ConnectionMediaType (DShowPin *, AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_QueryPinInfo (DShowPin *, PIN_INFO *); +long WINAPI ff_dshow_pin_QueryDirection (DShowPin *, PIN_DIRECTION *); +long WINAPI ff_dshow_pin_QueryId (DShowPin *, wchar_t **); +long WINAPI ff_dshow_pin_QueryAccept (DShowPin *, const AM_MEDIA_TYPE *); +long WINAPI ff_dshow_pin_EnumMediaTypes (DShowPin *, IEnumMediaTypes **); +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *, IPin **, unsigned long *); +long WINAPI ff_dshow_pin_EndOfStream (DShowPin *); +long WINAPI ff_dshow_pin_BeginFlush (DShowPin *); +long WINAPI ff_dshow_pin_EndFlush (DShowPin *); +long WINAPI ff_dshow_pin_NewSegment (DShowPin *, REFERENCE_TIME, REFERENCE_TIME, double); -long ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); -unsigned long ff_dshow_meminputpin_AddRef (DShowMemInputPin *); -unsigned long ff_dshow_meminputpin_Release (DShowMemInputPin *); -long ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); -long ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); -long ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); -long ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); -long ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_QueryInterface (DShowMemInputPin *, const GUID *, void **); +unsigned long WINAPI ff_dshow_meminputpin_AddRef (DShowMemInputPin *); +unsigned long WINAPI ff_dshow_meminputpin_Release (DShowMemInputPin *); +long WINAPI ff_dshow_meminputpin_GetAllocator (DShowMemInputPin *, IMemAllocator **); +long WINAPI ff_dshow_meminputpin_NotifyAllocator (DShowMemInputPin *, IMemAllocator *, BOOL); +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *, ALLOCATOR_PROPERTIES *); +long WINAPI ff_dshow_meminputpin_Receive (DShowMemInputPin *, IMediaSample *); +long WINAPI ff_dshow_meminputpin_ReceiveMultiple (DShowMemInputPin *, IMediaSample **, long, long *); +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock (DShowMemInputPin *); void ff_dshow_pin_Destroy(DShowPin *); DShowPin *ff_dshow_pin_Create (DShowFilter *filter); @@ -212,13 +212,13 @@ struct DShowEnumPins { DShowFilter *filter; }; -long ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); -unsigned long ff_dshow_enumpins_AddRef (DShowEnumPins *); -unsigned long ff_dshow_enumpins_Release (DShowEnumPins *); -long ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); -long ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); -long ff_dshow_enumpins_Reset (DShowEnumPins *); -long ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); +long WINAPI ff_dshow_enumpins_QueryInterface(DShowEnumPins *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enumpins_AddRef (DShowEnumPins *); +unsigned long WINAPI ff_dshow_enumpins_Release (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Next (DShowEnumPins *, unsigned long, IPin **, unsigned long *); +long WINAPI ff_dshow_enumpins_Skip (DShowEnumPins *, unsigned long); +long WINAPI ff_dshow_enumpins_Reset (DShowEnumPins *); +long WINAPI ff_dshow_enumpins_Clone (DShowEnumPins *, DShowEnumPins **); void ff_dshow_enumpins_Destroy(DShowEnumPins *); DShowEnumPins *ff_dshow_enumpins_Create (DShowPin *pin, DShowFilter *filter); @@ -233,13 +233,13 @@ struct DShowEnumMediaTypes { AM_MEDIA_TYPE type; }; -long ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); -unsigned long ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); -unsigned long ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); -long ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); -long ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); -long ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); +long WINAPI ff_dshow_enummediatypes_QueryInterface(DShowEnumMediaTypes *, const GUID *, void **); +unsigned long WINAPI ff_dshow_enummediatypes_AddRef (DShowEnumMediaTypes *); +unsigned long WINAPI ff_dshow_enummediatypes_Release (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Next (DShowEnumMediaTypes *, unsigned long, AM_MEDIA_TYPE **, unsigned long *); +long WINAPI ff_dshow_enummediatypes_Skip (DShowEnumMediaTypes *, unsigned long); +long WINAPI ff_dshow_enummediatypes_Reset (DShowEnumMediaTypes *); +long WINAPI ff_dshow_enummediatypes_Clone (DShowEnumMediaTypes *, DShowEnumMediaTypes **); void ff_dshow_enummediatypes_Destroy(DShowEnumMediaTypes *); DShowEnumMediaTypes *ff_dshow_enummediatypes_Create(const AM_MEDIA_TYPE *type); @@ -262,21 +262,21 @@ struct DShowFilter { void (*callback)(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time, enum dshowDeviceType type); }; -long ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); -unsigned long ff_dshow_filter_AddRef (DShowFilter *); -unsigned long ff_dshow_filter_Release (DShowFilter *); -long ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); -long ff_dshow_filter_Stop (DShowFilter *); -long ff_dshow_filter_Pause (DShowFilter *); -long ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); -long ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); -long ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); -long ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); -long ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); -long ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); -long ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); -long ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); -long ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); +long WINAPI ff_dshow_filter_QueryInterface (DShowFilter *, const GUID *, void **); +unsigned long WINAPI ff_dshow_filter_AddRef (DShowFilter *); +unsigned long WINAPI ff_dshow_filter_Release (DShowFilter *); +long WINAPI ff_dshow_filter_GetClassID (DShowFilter *, CLSID *); +long WINAPI ff_dshow_filter_Stop (DShowFilter *); +long WINAPI ff_dshow_filter_Pause (DShowFilter *); +long WINAPI ff_dshow_filter_Run (DShowFilter *, REFERENCE_TIME); +long WINAPI ff_dshow_filter_GetState (DShowFilter *, DWORD, FILTER_STATE *); +long WINAPI ff_dshow_filter_SetSyncSource (DShowFilter *, IReferenceClock *); +long WINAPI ff_dshow_filter_GetSyncSource (DShowFilter *, IReferenceClock **); +long WINAPI ff_dshow_filter_EnumPins (DShowFilter *, IEnumPins **); +long WINAPI ff_dshow_filter_FindPin (DShowFilter *, const wchar_t *, IPin **); +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *, FILTER_INFO *); +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *, IFilterGraph *, const wchar_t *); +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *, wchar_t **); void ff_dshow_filter_Destroy(DShowFilter *); DShowFilter *ff_dshow_filter_Create (void *, void *, enum dshowDeviceType); @@ -312,6 +312,7 @@ struct dshow_ctx { char *audio_filter_save_file; char *video_filter_load_file; char *video_filter_save_file; + int use_video_device_timestamps; IBaseFilter *device_filter[2]; IPin *device_pin[2]; @@ -321,7 +322,7 @@ struct dshow_ctx { HANDLE mutex; HANDLE event[2]; /* event[0] is set by DirectShow * event[1] is set by callback() */ - PacketList *pktl; + PacketListEntry *pktl; int eof; diff --git a/libavdevice/dshow_crossbar.c b/libavdevice/dshow_crossbar.c index 2438683cde..961defe690 100644 --- a/libavdevice/dshow_crossbar.c +++ b/libavdevice/dshow_crossbar.c @@ -204,5 +204,9 @@ end: IAMTVTuner_Release(tv_tuner_filter); if (tv_tuner_base_filter) IBaseFilter_Release(tv_tuner_base_filter); + if (tv_audio_filter) + IAMAudioInputMixer_Release(tv_audio_filter); + if (tv_audio_base_filter) + IBaseFilter_Release(tv_audio_base_filter); return hr; } diff --git a/libavdevice/dshow_enummediatypes.c b/libavdevice/dshow_enummediatypes.c index 82944507f6..4cb7057e17 100644 --- a/libavdevice/dshow_enummediatypes.c +++ b/libavdevice/dshow_enummediatypes.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enummediatypes, DShowEnumMediaTypes, DECLARE_ADDREF(enummediatypes, DShowEnumMediaTypes) DECLARE_RELEASE(enummediatypes, DShowEnumMediaTypes) -long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, +long WINAPI ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, AM_MEDIA_TYPE **types, unsigned long *fetched) { int count = 0; @@ -50,20 +50,20 @@ long ff_dshow_enummediatypes_Next(DShowEnumMediaTypes *this, unsigned long n, return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) +long WINAPI ff_dshow_enummediatypes_Skip(DShowEnumMediaTypes *this, unsigned long n) { dshowdebug("ff_dshow_enummediatypes_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid type. */ return S_FALSE; return S_OK; } -long ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) +long WINAPI ff_dshow_enummediatypes_Reset(DShowEnumMediaTypes *this) { dshowdebug("ff_dshow_enummediatypes_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) +long WINAPI ff_dshow_enummediatypes_Clone(DShowEnumMediaTypes *this, DShowEnumMediaTypes **enums) { DShowEnumMediaTypes *new; dshowdebug("ff_dshow_enummediatypes_Clone(%p)\n", this); diff --git a/libavdevice/dshow_enumpins.c b/libavdevice/dshow_enumpins.c index 6bf59928f9..759b589ade 100644 --- a/libavdevice/dshow_enumpins.c +++ b/libavdevice/dshow_enumpins.c @@ -26,7 +26,7 @@ DECLARE_QUERYINTERFACE(enumpins, DShowEnumPins, DECLARE_ADDREF(enumpins, DShowEnumPins) DECLARE_RELEASE(enumpins, DShowEnumPins) -long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, +long WINAPI ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, unsigned long *fetched) { int count = 0; @@ -45,20 +45,20 @@ long ff_dshow_enumpins_Next(DShowEnumPins *this, unsigned long n, IPin **pins, return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) +long WINAPI ff_dshow_enumpins_Skip(DShowEnumPins *this, unsigned long n) { dshowdebug("ff_dshow_enumpins_Skip(%p)\n", this); if (n) /* Any skip will always fall outside of the only valid pin. */ return S_FALSE; return S_OK; } -long ff_dshow_enumpins_Reset(DShowEnumPins *this) +long WINAPI ff_dshow_enumpins_Reset(DShowEnumPins *this) { dshowdebug("ff_dshow_enumpins_Reset(%p)\n", this); this->pos = 0; return S_OK; } -long ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) +long WINAPI ff_dshow_enumpins_Clone(DShowEnumPins *this, DShowEnumPins **pins) { DShowEnumPins *new; dshowdebug("ff_dshow_enumpins_Clone(%p)\n", this); diff --git a/libavdevice/dshow_filter.c b/libavdevice/dshow_filter.c index 61e057a836..4642ac077c 100644 --- a/libavdevice/dshow_filter.c +++ b/libavdevice/dshow_filter.c @@ -26,32 +26,32 @@ DECLARE_QUERYINTERFACE(filter, DShowFilter, DECLARE_ADDREF(filter, DShowFilter) DECLARE_RELEASE(filter, DShowFilter) -long ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) +long WINAPI ff_dshow_filter_GetClassID(DShowFilter *this, CLSID *id) { dshowdebug("ff_dshow_filter_GetClassID(%p)\n", this); /* I'm not creating a ClassID just for this. */ return E_FAIL; } -long ff_dshow_filter_Stop(DShowFilter *this) +long WINAPI ff_dshow_filter_Stop(DShowFilter *this) { dshowdebug("ff_dshow_filter_Stop(%p)\n", this); this->state = State_Stopped; return S_OK; } -long ff_dshow_filter_Pause(DShowFilter *this) +long WINAPI ff_dshow_filter_Pause(DShowFilter *this) { dshowdebug("ff_dshow_filter_Pause(%p)\n", this); this->state = State_Paused; return S_OK; } -long ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) +long WINAPI ff_dshow_filter_Run(DShowFilter *this, REFERENCE_TIME start) { dshowdebug("ff_dshow_filter_Run(%p) %"PRId64"\n", this, start); this->state = State_Running; this->start_time = start; return S_OK; } -long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) +long WINAPI ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) { dshowdebug("ff_dshow_filter_GetState(%p)\n", this); if (!state) @@ -59,7 +59,7 @@ long ff_dshow_filter_GetState(DShowFilter *this, DWORD ms, FILTER_STATE *state) *state = this->state; return S_OK; } -long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) +long WINAPI ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) { dshowdebug("ff_dshow_filter_SetSyncSource(%p)\n", this); @@ -73,7 +73,7 @@ long ff_dshow_filter_SetSyncSource(DShowFilter *this, IReferenceClock *clock) return S_OK; } -long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) +long WINAPI ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) { dshowdebug("ff_dshow_filter_GetSyncSource(%p)\n", this); @@ -85,7 +85,7 @@ long ff_dshow_filter_GetSyncSource(DShowFilter *this, IReferenceClock **clock) return S_OK; } -long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) +long WINAPI ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) { DShowEnumPins *new; dshowdebug("ff_dshow_filter_EnumPins(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_filter_EnumPins(DShowFilter *this, IEnumPins **enumpin) *enumpin = (IEnumPins *) new; return S_OK; } -long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) +long WINAPI ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) { DShowPin *found = NULL; dshowdebug("ff_dshow_filter_FindPin(%p)\n", this); @@ -116,7 +116,7 @@ long ff_dshow_filter_FindPin(DShowFilter *this, const wchar_t *id, IPin **pin) return S_OK; } -long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) +long WINAPI ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) { dshowdebug("ff_dshow_filter_QueryFilterInfo(%p)\n", this); @@ -128,7 +128,7 @@ long ff_dshow_filter_QueryFilterInfo(DShowFilter *this, FILTER_INFO *info) return S_OK; } -long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, +long WINAPI ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, const wchar_t *name) { dshowdebug("ff_dshow_filter_JoinFilterGraph(%p)\n", this); @@ -139,7 +139,7 @@ long ff_dshow_filter_JoinFilterGraph(DShowFilter *this, IFilterGraph *graph, return S_OK; } -long ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) +long WINAPI ff_dshow_filter_QueryVendorInfo(DShowFilter *this, wchar_t **info) { dshowdebug("ff_dshow_filter_QueryVendorInfo(%p)\n", this); diff --git a/libavdevice/dshow_pin.c b/libavdevice/dshow_pin.c index 3dae405e65..f846b68918 100644 --- a/libavdevice/dshow_pin.c +++ b/libavdevice/dshow_pin.c @@ -29,13 +29,13 @@ DECLARE_QUERYINTERFACE(pin, DShowPin, DECLARE_ADDREF(pin, DShowPin) DECLARE_RELEASE(pin, DShowPin) -long ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_Connect(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_Connect(%p, %p, %p)\n", this, pin, type); /* Input pins receive connections. */ return S_FALSE; } -long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, +long WINAPI ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, const AM_MEDIA_TYPE *type) { enum dshowDeviceType devtype = this->filter->type; @@ -62,7 +62,7 @@ long ff_dshow_pin_ReceiveConnection(DShowPin *this, IPin *pin, return S_OK; } -long ff_dshow_pin_Disconnect(DShowPin *this) +long WINAPI ff_dshow_pin_Disconnect(DShowPin *this) { dshowdebug("ff_dshow_pin_Disconnect(%p)\n", this); @@ -75,7 +75,7 @@ long ff_dshow_pin_Disconnect(DShowPin *this) return S_OK; } -long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) +long WINAPI ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) { dshowdebug("ff_dshow_pin_ConnectedTo(%p)\n", this); @@ -88,7 +88,7 @@ long ff_dshow_pin_ConnectedTo(DShowPin *this, IPin **pin) return S_OK; } -long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_ConnectionMediaType(%p)\n", this); @@ -99,7 +99,7 @@ long ff_dshow_pin_ConnectionMediaType(DShowPin *this, AM_MEDIA_TYPE *type) return ff_copy_dshow_media_type(type, &this->type); } -long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) +long WINAPI ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) { dshowdebug("ff_dshow_pin_QueryPinInfo(%p)\n", this); @@ -115,7 +115,7 @@ long ff_dshow_pin_QueryPinInfo(DShowPin *this, PIN_INFO *info) return S_OK; } -long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) +long WINAPI ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) { dshowdebug("ff_dshow_pin_QueryDirection(%p)\n", this); if (!dir) @@ -123,7 +123,7 @@ long ff_dshow_pin_QueryDirection(DShowPin *this, PIN_DIRECTION *dir) *dir = PINDIR_INPUT; return S_OK; } -long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) +long WINAPI ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) { dshowdebug("ff_dshow_pin_QueryId(%p)\n", this); @@ -134,12 +134,12 @@ long ff_dshow_pin_QueryId(DShowPin *this, wchar_t **id) return S_OK; } -long ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) +long WINAPI ff_dshow_pin_QueryAccept(DShowPin *this, const AM_MEDIA_TYPE *type) { dshowdebug("ff_dshow_pin_QueryAccept(%p)\n", this); return S_FALSE; } -long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) +long WINAPI ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) { const AM_MEDIA_TYPE *type = NULL; DShowEnumMediaTypes *new; @@ -154,31 +154,31 @@ long ff_dshow_pin_EnumMediaTypes(DShowPin *this, IEnumMediaTypes **enumtypes) *enumtypes = (IEnumMediaTypes *) new; return S_OK; } -long ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, +long WINAPI ff_dshow_pin_QueryInternalConnections(DShowPin *this, IPin **pin, unsigned long *npin) { dshowdebug("ff_dshow_pin_QueryInternalConnections(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_pin_EndOfStream(DShowPin *this) +long WINAPI ff_dshow_pin_EndOfStream(DShowPin *this) { dshowdebug("ff_dshow_pin_EndOfStream(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_BeginFlush(DShowPin *this) +long WINAPI ff_dshow_pin_BeginFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_BeginFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_EndFlush(DShowPin *this) +long WINAPI ff_dshow_pin_EndFlush(DShowPin *this) { dshowdebug("ff_dshow_pin_EndFlush(%p)\n", this); /* I don't care. */ return S_OK; } -long ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, +long WINAPI ff_dshow_pin_NewSegment(DShowPin *this, REFERENCE_TIME start, REFERENCE_TIME stop, double rate) { dshowdebug("ff_dshow_pin_NewSegment(%p)\n", this); @@ -250,43 +250,43 @@ DECLARE_DESTROY(pin, DShowPin, ff_dshow_pin_Free) /***************************************************************************** * DShowMemInputPin ****************************************************************************/ -long ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, +long WINAPI ff_dshow_meminputpin_QueryInterface(DShowMemInputPin *this, const GUID *riid, void **ppvObject) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_QueryInterface(%p)\n", this); return ff_dshow_pin_QueryInterface(pin, riid, ppvObject); } -unsigned long ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_AddRef(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_AddRef(%p)\n", this); return ff_dshow_pin_AddRef(pin); } -unsigned long ff_dshow_meminputpin_Release(DShowMemInputPin *this) +unsigned long WINAPI ff_dshow_meminputpin_Release(DShowMemInputPin *this) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); dshowdebug("ff_dshow_meminputpin_Release(%p)\n", this); return ff_dshow_pin_Release(pin); } -long ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) +long WINAPI ff_dshow_meminputpin_GetAllocator(DShowMemInputPin *this, IMemAllocator **alloc) { dshowdebug("ff_dshow_meminputpin_GetAllocator(%p)\n", this); return VFW_E_NO_ALLOCATOR; } -long ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, +long WINAPI ff_dshow_meminputpin_NotifyAllocator(DShowMemInputPin *this, IMemAllocator *alloc, BOOL rdwr) { dshowdebug("ff_dshow_meminputpin_NotifyAllocator(%p)\n", this); return S_OK; } -long ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_GetAllocatorRequirements(DShowMemInputPin *this, ALLOCATOR_PROPERTIES *props) { dshowdebug("ff_dshow_meminputpin_GetAllocatorRequirements(%p)\n", this); return E_NOTIMPL; } -long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) +long WINAPI ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) { DShowPin *pin = (DShowPin *) ((uint8_t *) this - imemoffset); enum dshowDeviceType devtype = pin->filter->type; @@ -295,13 +295,15 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) uint8_t *buf; int buf_size; /* todo should be a long? */ int index; - int64_t curtime; - int64_t orig_curtime; - int64_t graphtime; + int64_t chosentime = 0; + int64_t sampletime = 0; + int64_t graphtime = 0; + int use_sample_time = 1; const char *devtypename = (devtype == VideoDevice) ? "video" : "audio"; IReferenceClock *clock = pin->filter->clock; int64_t dummy; struct dshow_ctx *ctx; + HRESULT hr; dshowdebug("ff_dshow_meminputpin_Receive(%p)\n", this); @@ -309,40 +311,50 @@ long ff_dshow_meminputpin_Receive(DShowMemInputPin *this, IMediaSample *sample) if (!sample) return E_POINTER; - IMediaSample_GetTime(sample, &orig_curtime, &dummy); - orig_curtime += pin->filter->start_time; - IReferenceClock_GetTime(clock, &graphtime); - if (devtype == VideoDevice) { - /* PTS from video devices is unreliable. */ - IReferenceClock_GetTime(clock, &curtime); - } else { - IMediaSample_GetTime(sample, &curtime, &dummy); - if(curtime > 400000000000000000LL) { - /* initial frames sometimes start < 0 (shown as a very large number here, - like 437650244077016960 which FFmpeg doesn't like. - TODO figure out math. For now just drop them. */ - av_log(NULL, AV_LOG_DEBUG, - "dshow dropping initial (or ending) audio frame with odd PTS too high %"PRId64"\n", curtime); - return S_OK; - } - curtime += pin->filter->start_time; - } - - buf_size = IMediaSample_GetActualDataLength(sample); - IMediaSample_GetPointer(sample, &buf); priv_data = pin->filter->priv_data; s = priv_data; ctx = s->priv_data; + + hr = IMediaSample_GetTime(sample, &sampletime, &dummy); + IReferenceClock_GetTime(clock, &graphtime); + if (devtype == VideoDevice && !ctx->use_video_device_timestamps) { + /* PTS from video devices is unreliable. */ + chosentime = graphtime; + use_sample_time = 0; + } else { + if (hr == VFW_E_SAMPLE_TIME_NOT_SET || sampletime == 0) { + chosentime = graphtime; + use_sample_time = 0; + av_log(s, AV_LOG_DEBUG, + "frame with missing sample timestamp encountered, falling back to graph timestamp\n"); + } + else if (sampletime > 400000000000000000LL) { + /* initial frames sometimes start < 0 (shown as a very large number here, + like 437650244077016960 which FFmpeg doesn't like). + TODO figure out math. For now just drop them. */ + av_log(s, AV_LOG_DEBUG, + "dropping initial (or ending) sample with odd PTS too high %"PRId64"\n", sampletime); + return S_OK; + } else + chosentime = sampletime; + } + // media sample time is relative to graph start time + sampletime += pin->filter->start_time; + if (use_sample_time) + chosentime += pin->filter->start_time; + + buf_size = IMediaSample_GetActualDataLength(sample); + IMediaSample_GetPointer(sample, &buf); index = pin->filter->stream_index; - av_log(NULL, AV_LOG_VERBOSE, "dshow passing through packet of type %s size %8d " + av_log(s, AV_LOG_VERBOSE, "passing through packet of type %s size %8d " "timestamp %"PRId64" orig timestamp %"PRId64" graph timestamp %"PRId64" diff %"PRId64" %s\n", - devtypename, buf_size, curtime, orig_curtime, graphtime, graphtime - orig_curtime, ctx->device_name[devtype]); - pin->filter->callback(priv_data, index, buf, buf_size, curtime, devtype); + devtypename, buf_size, chosentime, sampletime, graphtime, graphtime - sampletime, ctx->device_name[devtype]); + pin->filter->callback(priv_data, index, buf, buf_size, chosentime, devtype); return S_OK; } -long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, +long WINAPI ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, IMediaSample **samples, long n, long *nproc) { int i; @@ -354,7 +366,7 @@ long ff_dshow_meminputpin_ReceiveMultiple(DShowMemInputPin *this, *nproc = n; return S_OK; } -long ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) +long WINAPI ff_dshow_meminputpin_ReceiveCanBlock(DShowMemInputPin *this) { dshowdebug("ff_dshow_meminputpin_ReceiveCanBlock(%p)\n", this); /* I swear I will not block. */ diff --git a/libavdevice/iec61883.c b/libavdevice/iec61883.c index e7b71c757a..72e14abff2 100644 --- a/libavdevice/iec61883.c +++ b/libavdevice/iec61883.c @@ -220,6 +220,7 @@ static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt) static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) { +#if CONFIG_MPEGTS_DEMUXER DVPacket *packet; int size; @@ -235,7 +236,7 @@ static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt) if (size > 0) return size; } - +#endif return -1; } diff --git a/libavdevice/jack.c b/libavdevice/jack.c index 31534134f3..0d5465e407 100644 --- a/libavdevice/jack.c +++ b/libavdevice/jack.c @@ -167,7 +167,7 @@ static int start_jack(AVFormatContext *context) /* Register JACK ports */ for (i = 0; i < self->nports; i++) { - char str[16]; + char str[32]; snprintf(str, sizeof(str), "input_%d", i + 1); self->ports[i] = jack_port_register(self->client, str, JACK_DEFAULT_AUDIO_TYPE, diff --git a/libavdevice/lavfi.c b/libavdevice/lavfi.c index 4eb1f56f7d..710ad7c530 100644 --- a/libavdevice/lavfi.c +++ b/libavdevice/lavfi.c @@ -76,7 +76,7 @@ static int *create_all_formats(int n) if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) fmts[j++] = i; } - fmts[j] = -1; + fmts[j] = AV_PIX_FMT_NONE; return fmts; } @@ -150,15 +150,12 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if (avctx->protocol_whitelist && (ret = av_dict_set(&options, "protocol_whitelist", avctx->protocol_whitelist, 0)) < 0) goto end; ret = avio_open2(&avio, lavfi->graph_filename, AVIO_FLAG_READ, &avctx->interrupt_callback, &options); - av_dict_set(&options, "protocol_whitelist", NULL, 0); + av_dict_free(&options); if (ret < 0) goto end; av_bprint_init(&graph_file_pb, 0, AV_BPRINT_SIZE_UNLIMITED); ret = avio_read_to_bprint(avio, &graph_file_pb, INT_MAX); avio_closep(&avio); - av_bprint_chars(&graph_file_pb, '\0', 1); - if (!ret && !av_bprint_is_complete(&graph_file_pb)) - ret = AVERROR(ENOMEM); if (ret) { av_bprint_finalize(&graph_file_pb, NULL); goto end; @@ -272,17 +269,17 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) if (ret < 0) goto end; } else if (type == AVMEDIA_TYPE_AUDIO) { - enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_U8, - AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_DBL, -1 }; + static const enum AVSampleFormat sample_fmts[] = { + AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL, + }; ret = avfilter_graph_create_filter(&sink, abuffersink, inout->name, NULL, NULL, lavfi->graph); if (ret >= 0) - ret = av_opt_set_int_list(sink, "sample_fmts", sample_fmts, AV_SAMPLE_FMT_NONE, AV_OPT_SEARCH_CHILDREN); + ret = av_opt_set_bin(sink, "sample_fmts", (const uint8_t*)sample_fmts, + sizeof(sample_fmts), AV_OPT_SEARCH_CHILDREN); if (ret < 0) goto end; ret = av_opt_set_int(sink, "all_channel_counts", 1, @@ -320,29 +317,30 @@ av_cold static int lavfi_read_header(AVFormatContext *avctx) AVFilterContext *sink = lavfi->sinks[lavfi->stream_sink_map[i]]; AVRational time_base = av_buffersink_get_time_base(sink); AVStream *st = avctx->streams[i]; - st->codecpar->codec_type = av_buffersink_get_type(sink); + AVCodecParameters *const par = st->codecpar; avpriv_set_pts_info(st, 64, time_base.num, time_base.den); - if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_VIDEO) { - st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; - st->codecpar->format = av_buffersink_get_format(sink); - st->codecpar->width = av_buffersink_get_w(sink); - st->codecpar->height = av_buffersink_get_h(sink); + par->codec_type = av_buffersink_get_type(sink); + if (par->codec_type == AVMEDIA_TYPE_VIDEO) { + int64_t probesize; + par->codec_id = AV_CODEC_ID_RAWVIDEO; + par->format = av_buffersink_get_format(sink); + par->width = av_buffersink_get_w(sink); + par->height = av_buffersink_get_h(sink); + probesize = par->width * par->height * 30 * + av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(par->format)); + avctx->probesize = FFMAX(avctx->probesize, probesize); st ->sample_aspect_ratio = - st->codecpar->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); - avctx->probesize = FFMAX(avctx->probesize, - av_buffersink_get_w(sink) * av_buffersink_get_h(sink) * - av_get_padded_bits_per_pixel(av_pix_fmt_desc_get(av_buffersink_get_format(sink))) * - 30); - } else if (av_buffersink_get_type(sink) == AVMEDIA_TYPE_AUDIO) { - st->codecpar->codec_id = av_get_pcm_codec(av_buffersink_get_format(sink), -1); - st->codecpar->channels = av_buffersink_get_channels(sink); - st->codecpar->format = av_buffersink_get_format(sink); - st->codecpar->sample_rate = av_buffersink_get_sample_rate(sink); - st->codecpar->channel_layout = av_buffersink_get_channel_layout(sink); - if (st->codecpar->codec_id == AV_CODEC_ID_NONE) + 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); + 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) av_log(avctx, AV_LOG_ERROR, "Could not find PCM codec for sample format %s.\n", - av_get_sample_fmt_name(av_buffersink_get_format(sink))); + av_get_sample_fmt_name(par->format)); } } @@ -356,8 +354,6 @@ end: av_free(pix_fmts); avfilter_inout_free(&input_links); avfilter_inout_free(&output_links); - if (ret < 0) - lavfi_read_close(avctx); return ret; } @@ -507,4 +503,5 @@ const AVInputFormat ff_lavfi_demuxer = { .read_close = lavfi_read_close, .flags = AVFMT_NOFILE, .priv_class = &lavfi_class, + .flags_internal = FF_FMT_INIT_CLEANUP, }; diff --git a/libavdevice/v4l2.c b/libavdevice/v4l2.c index b5997fba33..2ecfb9fae7 100644 --- a/libavdevice/v4l2.c +++ b/libavdevice/v4l2.c @@ -1019,8 +1019,6 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l struct video_data *s = ctx->priv_data; DIR *dir; struct dirent *entry; - AVDeviceInfo *device = NULL; - struct v4l2_capability cap; int ret = 0; if (!device_list) @@ -1033,16 +1031,25 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l return ret; } while ((entry = readdir(dir))) { + AVDeviceInfo *device = NULL; + struct v4l2_capability cap; + int fd = -1, size; char device_name[256]; if (!v4l2_is_v4l_dev(entry->d_name)) continue; - snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); - if ((s->fd = device_open(ctx, device_name)) < 0) + size = snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name); + if (size >= sizeof(device_name)) { + av_log(ctx, AV_LOG_ERROR, "Device name too long.\n"); + ret = AVERROR(ENOSYS); + break; + } + + if ((fd = device_open(ctx, device_name)) < 0) continue; - if (v4l2_ioctl(s->fd, VIDIOC_QUERYCAP, &cap) < 0) { + if (v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) { ret = AVERROR(errno); av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", av_err2str(ret)); goto fail; @@ -1064,8 +1071,7 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l &device_list->nb_devices, device)) < 0) goto fail; - v4l2_close(s->fd); - s->fd = -1; + v4l2_close(fd); continue; fail: @@ -1074,9 +1080,7 @@ static int v4l2_get_device_list(AVFormatContext *ctx, AVDeviceInfoList *device_l av_freep(&device->device_description); av_freep(&device); } - if (s->fd >= 0) - v4l2_close(s->fd); - s->fd = -1; + v4l2_close(fd); break; } closedir(dir); diff --git a/libavdevice/version.h b/libavdevice/version.h index 8daeb0059a..05234e7f21 100644 --- a/libavdevice/version.h +++ b/libavdevice/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVDEVICE_VERSION_MAJOR 59 -#define LIBAVDEVICE_VERSION_MINOR 0 -#define LIBAVDEVICE_VERSION_MICRO 101 +#define LIBAVDEVICE_VERSION_MINOR 5 +#define LIBAVDEVICE_VERSION_MICRO 100 #define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ LIBAVDEVICE_VERSION_MINOR, \ @@ -46,8 +46,6 @@ * dropped at a future version bump. The defines themselves are not part of * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_DEVICE_CAPABILITIES #define FF_API_DEVICE_CAPABILITIES (LIBAVDEVICE_VERSION_MAJOR < 60) -#endif #endif /* AVDEVICE_VERSION_H */ diff --git a/libavdevice/vfwcap.c b/libavdevice/vfwcap.c index 6fad466f8a..86a40b4af4 100644 --- a/libavdevice/vfwcap.c +++ b/libavdevice/vfwcap.c @@ -45,7 +45,7 @@ struct vfw_ctx { HWND hwnd; HANDLE mutex; HANDLE event; - PacketList *pktl; + PacketListEntry *pktl; unsigned int curbufsize; unsigned int frame_num; char *video_size; /**< A string describing video size, set by a private option. */ @@ -179,7 +179,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) { AVFormatContext *s; struct vfw_ctx *ctx; - PacketList **ppktl, *pktl_next; + PacketListEntry **ppktl, *pktl_next; s = (AVFormatContext *) GetWindowLongPtr(hwnd, GWLP_USERDATA); ctx = s->priv_data; @@ -191,7 +191,7 @@ static LRESULT CALLBACK videostream_cb(HWND hwnd, LPVIDEOHDR vdhdr) WaitForSingleObject(ctx->mutex, INFINITE); - pktl_next = av_mallocz(sizeof(PacketList)); + pktl_next = av_mallocz(sizeof(*pktl_next)); if(!pktl_next) goto fail; @@ -220,7 +220,7 @@ fail: static int vfw_read_close(AVFormatContext *s) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl; + PacketListEntry *pktl; if(ctx->hwnd) { SendMessage(ctx->hwnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0); @@ -234,7 +234,7 @@ static int vfw_read_close(AVFormatContext *s) pktl = ctx->pktl; while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_free(pktl); pktl = next; @@ -440,7 +440,7 @@ fail: static int vfw_read_packet(AVFormatContext *s, AVPacket *pkt) { struct vfw_ctx *ctx = s->priv_data; - PacketList *pktl = NULL; + PacketListEntry *pktl = NULL; while(!pktl) { WaitForSingleObject(ctx->mutex, INFINITE); diff --git a/libavdevice/xcbgrab.c b/libavdevice/xcbgrab.c index 8164101c5e..64a68ba497 100644 --- a/libavdevice/xcbgrab.c +++ b/libavdevice/xcbgrab.c @@ -277,7 +277,7 @@ static int xcbgrab_frame_shm(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_ERROR, "Could not get shared memory buffer.\n"); return AVERROR(ENOMEM); } - segment = (xcb_shm_seg_t)av_buffer_pool_buffer_get_opaque(buf); + segment = (xcb_shm_seg_t)(uintptr_t)av_buffer_pool_buffer_get_opaque(buf); iq = xcb_shm_get_image(c->conn, drawable, c->x, c->y, c->width, c->height, ~0, diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 1b2de4f5b8..0bbdf3244d 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -44,6 +44,8 @@ OBJS-$(CONFIG_ADECORRELATE_FILTER) += af_adecorrelate.o OBJS-$(CONFIG_ADELAY_FILTER) += af_adelay.o OBJS-$(CONFIG_ADENORM_FILTER) += af_adenorm.o OBJS-$(CONFIG_ADERIVATIVE_FILTER) += af_aderivative.o +OBJS-$(CONFIG_ADYNAMICEQUALIZER_FILTER) += af_adynamicequalizer.o +OBJS-$(CONFIG_ADYNAMICSMOOTH_FILTER) += af_adynamicsmooth.o OBJS-$(CONFIG_AECHO_FILTER) += af_aecho.o OBJS-$(CONFIG_AEMPHASIS_FILTER) += af_aemphasis.o OBJS-$(CONFIG_AEVAL_FILTER) += aeval.o @@ -69,6 +71,7 @@ OBJS-$(CONFIG_AMIX_FILTER) += af_amix.o OBJS-$(CONFIG_AMULTIPLY_FILTER) += af_amultiply.o OBJS-$(CONFIG_ANEQUALIZER_FILTER) += af_anequalizer.o OBJS-$(CONFIG_ANLMDN_FILTER) += af_anlmdn.o +OBJS-$(CONFIG_ANLMF_FILTER) += af_anlms.o OBJS-$(CONFIG_ANLMS_FILTER) += af_anlms.o OBJS-$(CONFIG_ANULL_FILTER) += af_anull.o OBJS-$(CONFIG_APAD_FILTER) += af_apad.o @@ -92,6 +95,7 @@ OBJS-$(CONFIG_ASETTB_FILTER) += settb.o OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o OBJS-$(CONFIG_ASIDEDATA_FILTER) += f_sidedata.o OBJS-$(CONFIG_ASOFTCLIP_FILTER) += af_asoftclip.o +OBJS-$(CONFIG_ASPECTRALSTATS_FILTER) += af_aspectralstats.o OBJS-$(CONFIG_ASPLIT_FILTER) += split.o OBJS-$(CONFIG_ASR_FILTER) += af_asr.o OBJS-$(CONFIG_ASTATS_FILTER) += af_astats.o @@ -180,7 +184,7 @@ OBJS-$(CONFIG_ATADENOISE_FILTER) += vf_atadenoise.o OBJS-$(CONFIG_AVGBLUR_FILTER) += vf_avgblur.o OBJS-$(CONFIG_AVGBLUR_OPENCL_FILTER) += vf_avgblur_opencl.o opencl.o \ opencl/avgblur.o boxblur.o -OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER) += vf_avgblur_vulkan.o vulkan.o +OBJS-$(CONFIG_AVGBLUR_VULKAN_FILTER) += vf_avgblur_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_BBOX_FILTER) += bbox.o vf_bbox.o OBJS-$(CONFIG_BENCH_FILTER) += f_bench.o OBJS-$(CONFIG_BILATERAL_FILTER) += vf_bilateral.o @@ -188,13 +192,14 @@ 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_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 \ opencl/avgblur.o boxblur.o OBJS-$(CONFIG_BWDIF_FILTER) += vf_bwdif.o yadif_common.o OBJS-$(CONFIG_CAS_FILTER) += vf_cas.o -OBJS-$(CONFIG_CHROMABER_VULKAN_FILTER) += vf_chromaber_vulkan.o vulkan.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_CHROMANR_FILTER) += vf_chromanr.o @@ -290,6 +295,7 @@ OBJS-$(CONFIG_FREEZEFRAMES_FILTER) += vf_freezeframes.o OBJS-$(CONFIG_FREI0R_FILTER) += vf_frei0r.o OBJS-$(CONFIG_FSPP_FILTER) += vf_fspp.o qp_table.o OBJS-$(CONFIG_GBLUR_FILTER) += vf_gblur.o +OBJS-$(CONFIG_GBLUR_VULKAN_FILTER) += vf_gblur_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_GEQ_FILTER) += vf_geq.o OBJS-$(CONFIG_GRADFUN_FILTER) += vf_gradfun.o OBJS-$(CONFIG_GRAPHMONITOR_FILTER) += f_graphmonitor.o @@ -298,6 +304,7 @@ OBJS-$(CONFIG_GREYEDGE_FILTER) += vf_colorconstancy.o OBJS-$(CONFIG_GUIDED_FILTER) += vf_guided.o OBJS-$(CONFIG_HALDCLUT_FILTER) += vf_lut3d.o framesync.o OBJS-$(CONFIG_HFLIP_FILTER) += vf_hflip.o +OBJS-$(CONFIG_HFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_HISTEQ_FILTER) += vf_histeq.o OBJS-$(CONFIG_HISTOGRAM_FILTER) += vf_histogram.o OBJS-$(CONFIG_HQDN3D_FILTER) += vf_hqdn3d.o @@ -306,6 +313,7 @@ OBJS-$(CONFIG_HSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_HSVHOLD_FILTER) += vf_hsvkey.o OBJS-$(CONFIG_HSVKEY_FILTER) += vf_hsvkey.o OBJS-$(CONFIG_HUE_FILTER) += vf_hue.o +OBJS-$(CONFIG_HUESATURATION_FILTER) += vf_huesaturation.o OBJS-$(CONFIG_HWDOWNLOAD_FILTER) += vf_hwdownload.o OBJS-$(CONFIG_HWMAP_FILTER) += vf_hwmap.o OBJS-$(CONFIG_HWUPLOAD_CUDA_FILTER) += vf_hwupload_cuda.o @@ -323,6 +331,7 @@ OBJS-$(CONFIG_LAGFUN_FILTER) += vf_lagfun.o OBJS-$(CONFIG_LATENCY_FILTER) += f_latency.o OBJS-$(CONFIG_LENSCORRECTION_FILTER) += vf_lenscorrection.o OBJS-$(CONFIG_LENSFUN_FILTER) += vf_lensfun.o +OBJS-$(CONFIG_LIBPLACEBO_FILTER) += vf_libplacebo.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_LIBVMAF_FILTER) += vf_libvmaf.o framesync.o OBJS-$(CONFIG_LIMITDIFF_FILTER) += vf_limitdiff.o framesync.o OBJS-$(CONFIG_LIMITER_FILTER) += vf_limiter.o @@ -352,7 +361,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_NEGATE_FILTER) += vf_lut.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 OBJS-$(CONFIG_NNEDI_FILTER) += vf_nnedi.o @@ -369,7 +378,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_VULKAN_FILTER) += vf_overlay_vulkan.o vulkan.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 OBJS-$(CONFIG_PAD_OPENCL_FILTER) += vf_pad_opencl.o opencl.o opencl/pad.o @@ -414,8 +423,9 @@ OBJS-$(CONFIG_SCALE_CUDA_FILTER) += vf_scale_cuda.o scale_eval.o \ OBJS-$(CONFIG_SCALE_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o -OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o +OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o +OBJS-$(CONFIG_SCALE2REF_NPP_FILTER) += vf_scale_npp.o scale_eval.o OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o OBJS-$(CONFIG_SCHARR_FILTER) += vf_convolution.o OBJS-$(CONFIG_SCROLL_FILTER) += vf_scroll.o @@ -478,6 +488,7 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER) += vf_transpose_npp.o OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o opencl/transpose.o OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o +OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vf_transpose_vulkan.o vulkan.o vulkan_filter.o OBJS-$(CONFIG_TRIM_FILTER) += trim.o OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o OBJS-$(CONFIG_UNSHARP_FILTER) += vf_unsharp.o @@ -490,6 +501,7 @@ OBJS-$(CONFIG_VAGUEDENOISER_FILTER) += vf_vaguedenoiser.o OBJS-$(CONFIG_VARBLUR_FILTER) += vf_varblur.o framesync.o OBJS-$(CONFIG_VECTORSCOPE_FILTER) += vf_vectorscope.o OBJS-$(CONFIG_VFLIP_FILTER) += vf_vflip.o +OBJS-$(CONFIG_VFLIP_VULKAN_FILTER) += vf_flip_vulkan.o vulkan.o OBJS-$(CONFIG_VFRDET_FILTER) += vf_vfrdet.o OBJS-$(CONFIG_VIBRANCE_FILTER) += vf_vibrance.o OBJS-$(CONFIG_VIDSTABDETECT_FILTER) += vidstabutils.o vf_vidstabdetect.o @@ -511,6 +523,10 @@ OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o OBJS-$(CONFIG_YADIF_CUDA_FILTER) += vf_yadif_cuda.o vf_yadif_cuda.ptx.o \ yadif_common.o cuda/load_helper.o +OBJS-$(CONFIG_YADIF_VIDEOTOOLBOX_FILTER) += vf_yadif_videotoolbox.o \ + metal/vf_yadif_videotoolbox.metallib.o \ + metal/utils.o \ + yadif_common.o OBJS-$(CONFIG_YAEPBLUR_FILTER) += vf_yaepblur.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o @@ -520,6 +536,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_COLORSPECTRUM_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_COREIMAGESRC_FILTER) += vf_coreimage.o OBJS-$(CONFIG_FREI0R_SRC_FILTER) += vf_frei0r.o OBJS-$(CONFIG_GRADIENTS_FILTER) += vsrc_gradients.o @@ -563,22 +580,24 @@ OBJS-$(CONFIG_SPECTRUMSYNTH_FILTER) += vaf_spectrumsynth.o OBJS-$(CONFIG_AMOVIE_FILTER) += src_movie.o OBJS-$(CONFIG_MOVIE_FILTER) += src_movie.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o + # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avfilterres.o SKIPHEADERS-$(CONFIG_LIBVIDSTAB) += vidstabutils.h -OBJS-$(CONFIG_SHARED) += log2_tab.o - SKIPHEADERS-$(CONFIG_QSVVPP) += qsvvpp.h SKIPHEADERS-$(CONFIG_OPENCL) += opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_vpp.h -SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h - -OBJS-$(CONFIG_LIBGLSLANG) += glslang.o +SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h vulkan_filter.h TOOLS = graph2dot TESTPROGS = drawutils filtfmts formats integral +TESTPROGS-$(CONFIG_DNN) += dnn-layer-avgpool dnn-layer-conv2d dnn-layer-dense \ + dnn-layer-depth2space dnn-layer-mathbinary \ + dnn-layer-mathunary dnn-layer-maximum dnn-layer-pad \ TOOLS-$(CONFIG_LIBZMQ) += zmqsend diff --git a/libavfilter/af_acopy.c b/libavfilter/af_acopy.c index 32455d9186..1591ec9639 100644 --- a/libavfilter/af_acopy.c +++ b/libavfilter/af_acopy.c @@ -63,6 +63,7 @@ static const AVFilterPad acopy_outputs[] = { const AVFilter ff_af_acopy = { .name = "acopy", .description = NULL_IF_CONFIG_SMALL("Copy the input audio unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(acopy_inputs), FILTER_OUTPUTS(acopy_outputs), }; diff --git a/libavfilter/af_adelay.c b/libavfilter/af_adelay.c index c42fa2d175..ed8a8ae739 100644 --- a/libavfilter/af_adelay.c +++ b/libavfilter/af_adelay.c @@ -189,14 +189,15 @@ static int config_input(AVFilterLink *inlink) static int filter_frame(AVFilterLink *inlink, AVFrame *frame) { AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; AudioDelayContext *s = ctx->priv; AVFrame *out_frame; int i; if (ctx->is_disabled || !s->delays) - return ff_filter_frame(ctx->outputs[0], frame); + return ff_filter_frame(outlink, frame); - out_frame = ff_get_audio_buffer(ctx->outputs[0], frame->nb_samples); + out_frame = ff_get_audio_buffer(outlink, frame->nb_samples); if (!out_frame) { av_frame_free(&frame); return AVERROR(ENOMEM); @@ -215,9 +216,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) } out_frame->pts = s->next_pts; - s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, inlink->sample_rate}, inlink->time_base); + s->next_pts += av_rescale_q(frame->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); av_frame_free(&frame); - return ff_filter_frame(ctx->outputs[0], out_frame); + return ff_filter_frame(outlink, out_frame); } static int activate(AVFilterContext *ctx) diff --git a/libavfilter/af_adynamicequalizer.c b/libavfilter/af_adynamicequalizer.c new file mode 100644 index 0000000000..f377a5db3d --- /dev/null +++ b/libavfilter/af_adynamicequalizer.c @@ -0,0 +1,315 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" +#include "hermite.h" + +typedef struct AudioDynamicEqualizerContext { + const AVClass *class; + + double threshold; + double dfrequency; + double dqfactor; + double tfrequency; + double tqfactor; + double ratio; + double range; + double makeup; + double knee; + double slew; + double attack; + double release; + double attack_coef; + double release_coef; + int mode; + + AVFrame *state; +} AudioDynamicEqualizerContext; + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioDynamicEqualizerContext *s = ctx->priv; + + s->state = ff_get_audio_buffer(inlink, 8); + if (!s->state) + return AVERROR(ENOMEM); + + return 0; +} + +static double get_svf(double in, double *m, double *a, double *b) +{ + const double v0 = in; + const double v3 = v0 - b[1]; + const double v1 = a[0] * b[0] + a[1] * v3; + const double v2 = b[1] + a[1] * b[0] + a[2] * v3; + + b[0] = 2. * v1 - b[0]; + b[1] = 2. * v2 - b[1]; + + return m[0] * v0 + m[1] * v1 + m[2] * v2; +} + +static inline double from_dB(double x) +{ + return exp(0.05 * x * M_LN10); +} + +static inline double to_dB(double x) +{ + return 20. * log10(x); +} + +static inline double sqr(double x) +{ + return x * x; +} + +static double get_gain(double in, double srate, double makeup, + double aattack, double iratio, double knee, double range, + double thresdb, double slewfactor, double *state, + double attack_coeff, double release_coeff, double nc) +{ + double width = (6. * knee) + 0.01; + double cdb = 0.; + double Lgain = 1.; + double Lxg, Lxl, Lyg, Lyl, Ly1; + double checkwidth = 0.; + double slewwidth = 1.8; + int attslew = 0; + + Lyg = 0.; + Lxg = to_dB(fabs(in) + DBL_EPSILON); + + Lyg = Lxg + (iratio - 1.) * sqr(Lxg - thresdb + width * .5) / (2. * width); + + checkwidth = 2. * fabs(Lxg - thresdb); + if (2. * (Lxg - thresdb) < -width) { + Lyg = Lxg; + } else if (checkwidth <= width) { + Lyg = thresdb + (Lxg - thresdb) * iratio; + if (checkwidth <= slewwidth) { + if (Lyg >= state[2]) + attslew = 1; + } + } else if (2. * (Lxg-thresdb) > width) { + Lyg = thresdb + (Lxg - thresdb) * iratio; + } + + attack_coeff = attslew ? aattack : attack_coeff; + + Lxl = Lxg - Lyg; + + Ly1 = fmaxf(Lxl, release_coeff * state[1] +(1. - release_coeff) * Lxl); + Lyl = attack_coeff * state[0] + (1. - attack_coeff) * Ly1; + + cdb = -Lyl; + Lgain = from_dB(nc * fmin(cdb - makeup, range)); + + state[0] = Lyl; + state[1] = Ly1; + state[2] = Lyg; + + return Lgain; +} + +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioDynamicEqualizerContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + const double sample_rate = in->sample_rate; + const double makeup = s->makeup; + const double iratio = 1. / s->ratio; + 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 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 mode = s->mode; + const double knee = s->knee; + const double slew = s->slew; + const double aattack = exp(-1000. / ((s->attack + 2.0 * (slew - 1.)) * sample_rate)); + const double nc = mode == 0 ? 1. : -1.; + double da[3], dm[3]; + + { + double k = 1. / dqfactor; + + da[0] = 1. / (1. + dg * (dg + k)); + da[1] = dg * da[0]; + da[2] = dg * da[1]; + + dm[0] = 0.; + dm[1] = 1.; + dm[2] = 0.; + } + + for (int ch = start; ch < end; ch++) { + const double *src = (const double *)in->extended_data[ch]; + double *dst = (double *)out->extended_data[ch]; + double *state = (double *)s->state->extended_data[ch]; + + for (int n = 0; n < out->nb_samples; n++) { + double detect, gain, v, listen; + double fa[3], fm[3]; + + detect = listen = get_svf(src[n], dm, da, state); + detect = fabs(detect); + + gain = get_gain(detect, sample_rate, makeup, + aattack, iratio, knee, range, threshold, slew, + &state[4], attack, release, nc); + + { + double k = 1. / (tqfactor * gain); + + fa[0] = 1. / (1. + fg * (fg + k)); + fa[1] = fg * fa[0]; + fa[2] = fg * fa[1]; + + fm[0] = 1.; + fm[1] = k * (gain * gain - 1.); + fm[2] = 0.; + } + + v = get_svf(src[n], fm, fa, &state[2]); + v = mode == -1 ? listen : v; + dst[n] = ctx->is_disabled ? src[n] : v; + } + } + + return 0; +} + +static double get_coef(double x, double sr) +{ + return exp(-1000. / (x * sr)); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDynamicEqualizerContext *s = ctx->priv; + ThreadData td; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + s->attack_coef = get_coef(s->attack, in->sample_rate); + s->release_coef = get_coef(s->release, in->sample_rate); + + td.in = in; + td.out = out; + ff_filter_execute(ctx, filter_channels, &td, NULL, + FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx))); + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioDynamicEqualizerContext *s = ctx->priv; + + av_frame_free(&s->state); +} + +#define OFFSET(x) offsetof(AudioDynamicEqualizerContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption adynamicequalizer_options[] = { + { "threshold", "set detection threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS }, + { "dfrequency", "set detection frequency", OFFSET(dfrequency), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 1000000, FLAGS }, + { "dqfactor", "set detection Q factor", OFFSET(dqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, + { "tfrequency", "set target frequency", OFFSET(tfrequency), AV_OPT_TYPE_DOUBLE, {.dbl=1000}, 2, 1000000, FLAGS }, + { "tqfactor", "set target Q factor", OFFSET(tqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, + { "attack", "set attack duration", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 2000, FLAGS }, + { "release", "set release duration", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=200}, 1, 2000, FLAGS }, + { "knee", "set knee factor", OFFSET(knee), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 8, FLAGS }, + { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 20, FLAGS }, + { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 30, FLAGS }, + { "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 200, FLAGS }, + { "slew", "set slew factor", OFFSET(slew), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 200, FLAGS }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" }, + { "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" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(adynamicequalizer); + +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_adynamicequalizer = { + .name = "adynamicequalizer", + .description = NULL_IF_CONFIG_SMALL("Apply Dynamic Equalization of input audio."), + .priv_size = sizeof(AudioDynamicEqualizerContext), + .priv_class = &adynamicequalizer_class, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/af_adynamicsmooth.c b/libavfilter/af_adynamicsmooth.c new file mode 100644 index 0000000000..4e00fecc6a --- /dev/null +++ b/libavfilter/af_adynamicsmooth.c @@ -0,0 +1,142 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/ffmath.h" +#include "libavutil/opt.h" +#include "avfilter.h" +#include "audio.h" +#include "formats.h" + +typedef struct AudioDynamicSmoothContext { + const AVClass *class; + + double sensitivity; + double basefreq; + + AVFrame *coeffs; +} AudioDynamicSmoothContext; + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AudioDynamicSmoothContext *s = ctx->priv; + + s->coeffs = ff_get_audio_buffer(inlink, 3); + if (!s->coeffs) + return AVERROR(ENOMEM); + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioDynamicSmoothContext *s = ctx->priv; + const double sensitivity = s->sensitivity; + const double wc = s->basefreq / in->sample_rate; + AVFrame *out; + + if (av_frame_is_writable(in)) { + out = in; + } else { + out = ff_get_audio_buffer(outlink, in->nb_samples); + if (!out) { + av_frame_free(&in); + return AVERROR(ENOMEM); + } + av_frame_copy_props(out, in); + } + + for (int ch = 0; ch < out->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]; + double low1 = coeffs[0]; + double low2 = coeffs[1]; + double inz = coeffs[2]; + + for (int n = 0; n < out->nb_samples; n++) { + double low1z = low1; + double low2z = low2; + double bandz = low2z - low1z; + double wd = wc + sensitivity * fabs(bandz); + double g = fmin(1., wd * (5.9948827 + wd * (-11.969296 + wd * 15.959062))); + + low1 = low1z + g * (0.5 * (src[n] + inz) - low1z); + low2 = low2z + g * (0.5 * (low1 + low1z) - low2z); + inz = src[n]; + dst[n] = ctx->is_disabled ? src[n] : low2; + } + + coeffs[0] = low1; + coeffs[1] = low2; + coeffs[2] = inz; + } + + if (out != in) + av_frame_free(&in); + return ff_filter_frame(outlink, out); +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioDynamicSmoothContext *s = ctx->priv; + + av_frame_free(&s->coeffs); +} + +#define OFFSET(x) offsetof(AudioDynamicSmoothContext, x) +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption adynamicsmooth_options[] = { + { "sensitivity", "set smooth sensitivity", OFFSET(sensitivity), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 0, 1000000, FLAGS }, + { "basefreq", "set base frequency", OFFSET(basefreq), AV_OPT_TYPE_DOUBLE, {.dbl=22050}, 2, 1000000, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(adynamicsmooth); + +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_adynamicsmooth = { + .name = "adynamicsmooth", + .description = NULL_IF_CONFIG_SMALL("Apply Dynamic Smoothing of input audio."), + .priv_size = sizeof(AudioDynamicSmoothContext), + .priv_class = &adynamicsmooth_class, + .uninit = uninit, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c index 7e25c0c6a4..ed3c75311a 100644 --- a/libavfilter/af_aformat.c +++ b/libavfilter/af_aformat.c @@ -162,6 +162,7 @@ const AVFilter ff_af_aformat = { .uninit = uninit, .priv_size = sizeof(AFormatContext), .priv_class = &aformat_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_aformat_inputs), FILTER_OUTPUTS(avfilter_af_aformat_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_anlms.c b/libavfilter/af_anlms.c index f1f82b491d..f20e3c0e82 100644 --- a/libavfilter/af_anlms.c +++ b/libavfilter/af_anlms.c @@ -54,6 +54,8 @@ typedef struct AudioNLMSContext { AVFrame *frame[2]; + int anlmf; + AVFloatDSPContext *fdsp; } AudioNLMSContext; @@ -74,7 +76,7 @@ static const AVOption anlms_options[] = { { NULL } }; -AVFILTER_DEFINE_CLASS(anlms); +AVFILTER_DEFINE_CLASS_EXT(anlms, "anlm(f|s)", anlms_options); static int query_formats(AVFilterContext *ctx) { @@ -130,6 +132,8 @@ static float process_sample(AudioNLMSContext *s, float input, float desired, norm = s->eps + sum; b = mu * e / norm; + if (s->anlmf) + b *= 4.f * e * e; memcpy(tmp, delay + offset, order * sizeof(float)); @@ -241,6 +245,7 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; AudioNLMSContext *s = ctx->priv; + s->anlmf = !strcmp(ctx->filter->name, "anlmf"); s->kernel_size = FFALIGN(s->order, 16); if (!s->offset) @@ -312,3 +317,18 @@ const AVFilter ff_af_anlms = { .flags = AVFILTER_FLAG_SLICE_THREADS, .process_command = ff_filter_process_command, }; + +const AVFilter ff_af_anlmf = { + .name = "anlmf", + .description = NULL_IF_CONFIG_SMALL("Apply Normalized Least-Mean-Fourth algorithm to first audio stream."), + .priv_size = sizeof(AudioNLMSContext), + .priv_class = &anlms_class, + .init = init, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_QUERY_FUNC(query_formats), + .flags = AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/af_anull.c b/libavfilter/af_anull.c index 065d37e17e..78c5faeb23 100644 --- a/libavfilter/af_anull.c +++ b/libavfilter/af_anull.c @@ -44,6 +44,7 @@ static const AVFilterPad avfilter_af_anull_outputs[] = { const AVFilter ff_af_anull = { .name = "anull", .description = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_anull_inputs), FILTER_OUTPUTS(avfilter_af_anull_outputs), }; diff --git a/libavfilter/af_apad.c b/libavfilter/af_apad.c index 27259a87a3..ae73f0b6b1 100644 --- a/libavfilter/af_apad.c +++ b/libavfilter/af_apad.c @@ -52,8 +52,8 @@ static const AVOption apad_options[] = { { "packet_size", "set silence packet size", OFFSET(packet_size), AV_OPT_TYPE_INT, { .i64 = 4096 }, 0, INT_MAX, A }, { "pad_len", "set number of samples of silence to add", OFFSET(pad_len), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, A }, { "whole_len", "set minimum target number of samples in the audio stream", OFFSET(whole_len), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, A }, - { "pad_dur", "set duration of silence to add", OFFSET(pad_dur), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, A }, - { "whole_dur", "set minimum target duration in the audio stream", OFFSET(whole_dur), AV_OPT_TYPE_DURATION, { .i64 = 0 }, 0, INT64_MAX, A }, + { "pad_dur", "set duration of silence to add", OFFSET(pad_dur), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, A }, + { "whole_dur", "set minimum target duration in the audio stream", OFFSET(whole_dur), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT64_MAX, A }, { NULL } }; @@ -138,9 +138,9 @@ static int config_output(AVFilterLink *outlink) AVFilterContext *ctx = outlink->src; APadContext *s = ctx->priv; - if (s->pad_dur) + if (s->pad_dur >= 0) s->pad_len = av_rescale(s->pad_dur, outlink->sample_rate, AV_TIME_BASE); - if (s->whole_dur) + if (s->whole_dur >= 0) s->whole_len = av_rescale(s->whole_dur, outlink->sample_rate, AV_TIME_BASE); s->pad_len_left = s->pad_len; diff --git a/libavfilter/af_asdr.c b/libavfilter/af_asdr.c index 72b6dfa78b..addfe5f158 100644 --- a/libavfilter/af_asdr.c +++ b/libavfilter/af_asdr.c @@ -166,6 +166,7 @@ const AVFilter ff_af_asdr = { .priv_size = sizeof(AudioSDRContext), .activate = activate, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_DBLP), diff --git a/libavfilter/af_asetrate.c b/libavfilter/af_asetrate.c index 637fa4fbb8..76f29144e5 100644 --- a/libavfilter/af_asetrate.c +++ b/libavfilter/af_asetrate.c @@ -113,4 +113,5 @@ const AVFilter ff_af_asetrate = { FILTER_OUTPUTS(asetrate_outputs), FILTER_QUERY_FUNC(query_formats), .priv_class = &asetrate_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index b6623fa69d..c76756db63 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -257,6 +257,7 @@ const AVFilter ff_af_ashowinfo = { .description = NULL_IF_CONFIG_SMALL("Show textual information for each audio frame."), .priv_size = sizeof(AShowInfoContext), .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; diff --git a/libavfilter/af_aspectralstats.c b/libavfilter/af_aspectralstats.c new file mode 100644 index 0000000000..da418d22bf --- /dev/null +++ b/libavfilter/af_aspectralstats.c @@ -0,0 +1,605 @@ +/* + * Copyright (c) 2021 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "libavutil/audio_fifo.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" + +typedef struct ChannelSpectralStats { + float mean; + float variance; + float centroid; + float spread; + float skewness; + float kurtosis; + float entropy; + float flatness; + float crest; + float flux; + float slope; + float decrease; + float rolloff; +} ChannelSpectralStats; + +typedef struct AudioSpectralStatsContext { + const AVClass *class; + int win_size; + int win_func; + float overlap; + 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; +} AudioSpectralStatsContext; + +#define OFFSET(x) offsetof(AudioSpectralStatsContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +static const AVOption aspectralstats_options[] = { + { "win_size", "set the window size", OFFSET(win_size), AV_OPT_TYPE_INT, {.i64=2048}, 32, 65536, A }, + WIN_FUNC_OPTION("win_func", OFFSET(win_func), A, WFUNC_HANNING), + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, A }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(aspectralstats); + +static int config_output(AVFilterLink *outlink) +{ + AudioSpectralStatsContext *s = outlink->src->priv; + 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->window_func_lut = av_realloc_f(s->window_func_lut, s->win_size, + sizeof(*s->window_func_lut)); + if (!s->window_func_lut) + return AVERROR(ENOMEM); + generate_window_func(s->window_func_lut, s->win_size, s->win_func, &overlap); + if (s->overlap == 1.f) + s->overlap = overlap; + + s->hop_size = s->win_size * (1.f - s->overlap); + if (s->hop_size <= 0) + return AVERROR(EINVAL); + + s->stats = av_calloc(s->nb_channels, sizeof(*s->stats)); + if (!s->stats) + return AVERROR(ENOMEM); + + s->fft = av_calloc(s->nb_channels, sizeof(*s->fft)); + if (!s->fft) + return AVERROR(ENOMEM); + + s->magnitude = av_calloc(s->nb_channels, sizeof(*s->magnitude)); + if (!s->magnitude) + return AVERROR(ENOMEM); + + s->prev_magnitude = av_calloc(s->nb_channels, sizeof(*s->prev_magnitude)); + if (!s->prev_magnitude) + return AVERROR(ENOMEM); + + s->fft_in = av_calloc(s->nb_channels, sizeof(*s->fft_in)); + if (!s->fft_in) + return AVERROR(ENOMEM); + + s->fft_out = av_calloc(s->nb_channels, sizeof(*s->fft_out)); + if (!s->fft_out) + return AVERROR(ENOMEM); + + for (int ch = 0; ch < s->nb_channels; ch++) { + ret = av_tx_init(&s->fft[ch], &s->tx_fn, AV_TX_FLOAT_FFT, 0, s->win_size, &scale, 0); + if (ret < 0) + return ret; + + s->fft_in[ch] = av_calloc(s->win_size, sizeof(**s->fft_in)); + if (!s->fft_in[ch]) + return AVERROR(ENOMEM); + + s->fft_out[ch] = av_calloc(s->win_size, sizeof(**s->fft_out)); + if (!s->fft_out[ch]) + return AVERROR(ENOMEM); + + s->magnitude[ch] = av_calloc(s->win_size, sizeof(**s->magnitude)); + if (!s->magnitude[ch]) + return AVERROR(ENOMEM); + + s->prev_magnitude[ch] = av_calloc(s->win_size, sizeof(**s->prev_magnitude)); + if (!s->prev_magnitude[ch]) + return AVERROR(ENOMEM); + } + + return 0; +} + +static void set_meta(AVDictionary **metadata, int chan, const char *key, + const char *fmt, float val) +{ + uint8_t value[128]; + uint8_t key2[128]; + + snprintf(value, sizeof(value), fmt, val); + if (chan) + snprintf(key2, sizeof(key2), "lavfi.aspectralstats.%d.%s", chan, key); + else + snprintf(key2, sizeof(key2), "lavfi.aspectralstats.%s", key); + av_dict_set(metadata, key2, value, 0); +} + +static void set_metadata(AudioSpectralStatsContext *s, AVDictionary **metadata) +{ + for (int ch = 0; ch < s->nb_channels; ch++) { + ChannelSpectralStats *stats = &s->stats[ch]; + + set_meta(metadata, ch + 1, "mean", "%g", stats->mean); + set_meta(metadata, ch + 1, "variance", "%g", stats->variance); + set_meta(metadata, ch + 1, "centroid", "%g", stats->centroid); + set_meta(metadata, ch + 1, "spread", "%g", stats->spread); + set_meta(metadata, ch + 1, "skewness", "%g", stats->skewness); + set_meta(metadata, ch + 1, "kurtosis", "%g", stats->kurtosis); + set_meta(metadata, ch + 1, "entropy", "%g", stats->entropy); + set_meta(metadata, ch + 1, "flatness", "%g", stats->flatness); + set_meta(metadata, ch + 1, "crest", "%g", stats->crest); + set_meta(metadata, ch + 1, "flux", "%g", stats->flux); + set_meta(metadata, ch + 1, "slope", "%g", stats->slope); + set_meta(metadata, ch + 1, "decrease", "%g", stats->decrease); + set_meta(metadata, ch + 1, "rolloff", "%g", stats->rolloff); + } +} + +static float spectral_mean(const float *const spectral, int size, int max_freq) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += spectral[n]; + + return sum / size; +} + +static float sqrf(float a) +{ + return a * a; +} + +static float spectral_variance(const float *const spectral, int size, int max_freq, float mean) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += sqrf(spectral[n] - mean); + + return sum / size; +} + +static float spectral_centroid(const float *const spectral, int size, int max_freq) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * n * scale; + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_spread(const float *const spectral, int size, int max_freq, float centroid) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * sqrf(n * scale - centroid); + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 1.f; + return sqrtf(num / den); +} + +static float cbrf(float a) +{ + return a * a * a; +} + +static float spectral_skewness(const float *const spectral, int size, int max_freq, float centroid, float spread) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * cbrf(n * scale - centroid); + den += spectral[n]; + } + + den *= cbrf(spread); + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_kurtosis(const float *const spectral, int size, int max_freq, float centroid, float spread) +{ + const float scale = max_freq / (float)size; + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * sqrf(sqrf(n * scale - centroid)); + den += spectral[n]; + } + + den *= sqrf(sqrf(spread)); + if (den <= FLT_EPSILON) + return 1.f; + return num / den; +} + +static float spectral_entropy(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + num += spectral[n] * logf(spectral[n] + FLT_EPSILON); + } + + den = logf(size); + if (den <= FLT_EPSILON) + return 1.f; + return -num / den; +} + +static float spectral_flatness(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) { + float v = FLT_EPSILON + spectral[n]; + num += logf(v); + den += v; + } + + num /= size; + den /= size; + num = expf(num); + if (den <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_crest(const float *const spectral, int size, int max_freq) +{ + float max = 0.f, mean = 0.f; + + for (int n = 0; n < size; n++) { + max = fmaxf(max, spectral[n]); + mean += spectral[n]; + } + + mean /= size; + if (mean <= FLT_EPSILON) + return 0.f; + return max / mean; +} + +static float spectral_flux(const float *const spectral, const float *const prev_spectral, + int size, int max_freq) +{ + float sum = 0.f; + + for (int n = 0; n < size; n++) + sum += sqrf(spectral[n] - prev_spectral[n]); + + return sqrtf(sum); +} + +static float spectral_slope(const float *const spectral, int size, int max_freq) +{ + const float mean_freq = size * 0.5f; + float mean_spectral = 0.f, num = 0.f, den = 0.f; + + for (int n = 0; n < size; n++) + mean_spectral += spectral[n]; + mean_spectral /= size; + + for (int n = 0; n < size; n++) { + num += ((n - mean_freq) / mean_freq) * (spectral[n] - mean_spectral); + den += sqrf((n - mean_freq) / mean_freq); + } + + if (fabsf(den) <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_decrease(const float *const spectral, int size, int max_freq) +{ + float num = 0.f, den = 0.f; + + for (int n = 1; n < size; n++) { + num += (spectral[n] - spectral[0]) / n; + den += spectral[n]; + } + + if (den <= FLT_EPSILON) + return 0.f; + return num / den; +} + +static float spectral_rolloff(const float *const spectral, int size, int max_freq) +{ + const float scale = max_freq / (float)size; + float norm = 0.f, sum = 0.f; + int idx = 0.f; + + for (int n = 0; n < size; n++) + norm += spectral[n]; + norm *= 0.85f; + + for (int n = 0; n < size; n++) { + sum += spectral[n]; + if (sum >= norm) { + idx = n; + break; + } + } + + return idx * scale; +} + +static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AudioSpectralStatsContext *s = ctx->priv; + 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; + + for (int ch = start; ch < end; ch++) { + const float *const src = (const float *const)in->extended_data[ch]; + ChannelSpectralStats *stats = &s->stats[ch]; + AVComplexFloat *fft_out = s->fft_out[ch]; + AVComplexFloat *fft_in = s->fft_in[ch]; + float *magnitude = s->magnitude[ch]; + 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; + } + + for (int n = in->nb_samples; n < s->win_size; n++) { + fft_in[n].re = 0; + fft_in[n].im = 0; + } + + s->tx_fn(s->fft[ch], fft_out, fft_in, sizeof(float)); + + for (int n = 0; n < s->win_size / 2; n++) { + fft_out[n].re *= scale; + fft_out[n].im *= scale; + } + + for (int n = 0; n < s->win_size / 2; n++) + magnitude[n] = hypotf(fft_out[n].re, fft_out[n].im); + + stats->mean = spectral_mean(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->variance = spectral_variance(magnitude, s->win_size / 2, in->sample_rate / 2, stats->mean); + stats->centroid = spectral_centroid(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->spread = spectral_spread(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid); + stats->skewness = spectral_skewness(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid, stats->spread); + stats->kurtosis = spectral_kurtosis(magnitude, s->win_size / 2, in->sample_rate / 2, stats->centroid, stats->spread); + stats->entropy = spectral_entropy(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->flatness = spectral_flatness(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->crest = spectral_crest(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->flux = spectral_flux(magnitude, prev_magnitude, s->win_size / 2, in->sample_rate / 2); + stats->slope = spectral_slope(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->decrease = spectral_decrease(magnitude, s->win_size / 2, in->sample_rate / 2); + stats->rolloff = spectral_rolloff(magnitude, s->win_size / 2, in->sample_rate / 2); + + memcpy(prev_magnitude, magnitude, s->win_size * sizeof(float)); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + AVFilterLink *outlink = ctx->outputs[0]; + AudioSpectralStatsContext *s = ctx->priv; + AVDictionary **metadata; + AVFrame *out, *in = NULL; + int ret = 0; + + 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) + return AVERROR(ENOMEM); + } + + 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))); + + 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); + return ff_filter_frame(outlink, out); +fail: + av_frame_free(&in); + return ret < 0 ? ret : 0; +} + +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; + + 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); + 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); + return 0; + } + + if (!s->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; +} + +static av_cold void uninit(AVFilterContext *ctx) +{ + AudioSpectralStatsContext *s = ctx->priv; + + for (int ch = 0; ch < s->nb_channels; ch++) { + if (s->fft) + av_tx_uninit(&s->fft[ch]); + if (s->fft_in) + av_freep(&s->fft_in[ch]); + if (s->fft_out) + av_freep(&s->fft_out[ch]); + if (s->magnitude) + av_freep(&s->magnitude[ch]); + if (s->prev_magnitude) + av_freep(&s->prev_magnitude[ch]); + } + + av_freep(&s->fft); + av_freep(&s->magnitude); + av_freep(&s->prev_magnitude); + av_freep(&s->fft_in); + av_freep(&s->fft_out); + av_freep(&s->stats); + + av_freep(&s->window_func_lut); + av_audio_fifo_free(s->fifo); + s->fifo = NULL; +} + +static const AVFilterPad aspectralstats_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + }, +}; + +static const AVFilterPad aspectralstats_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_AUDIO, + .config_props = config_output, + }, +}; + +const AVFilter ff_af_aspectralstats = { + .name = "aspectralstats", + .description = NULL_IF_CONFIG_SMALL("Show frequency domain statistics about audio frames."), + .priv_size = sizeof(AudioSpectralStatsContext), + .priv_class = &aspectralstats_class, + .uninit = uninit, + .activate = activate, + FILTER_INPUTS(aspectralstats_inputs), + FILTER_OUTPUTS(aspectralstats_outputs), + FILTER_SINGLE_SAMPLEFMT(AV_SAMPLE_FMT_FLTP), + .flags = AVFILTER_FLAG_SLICE_THREADS, +}; diff --git a/libavfilter/af_asr.c b/libavfilter/af_asr.c index b9c7068526..42250e79e2 100644 --- a/libavfilter/af_asr.c +++ b/libavfilter/af_asr.c @@ -172,6 +172,7 @@ const AVFilter ff_af_asr = { .priv_class = &asr_class, .init = asr_init, .uninit = asr_uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asr_inputs), FILTER_OUTPUTS(asr_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_astats.c b/libavfilter/af_astats.c index 0621d18b35..6c79257cb4 100644 --- a/libavfilter/af_astats.c +++ b/libavfilter/af_astats.c @@ -114,8 +114,8 @@ typedef struct AudioStatsContext { static const AVOption astats_options[] = { { "length", "set the window length", OFFSET(time_constant), AV_OPT_TYPE_DOUBLE, {.dbl=.05}, 0, 10, FLAGS }, { "metadata", "inject metadata in the filtergraph", OFFSET(metadata), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, - { "reset", "recalculate stats after this many frames", OFFSET(reset_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, - { "measure_perchannel", "only measure_perchannel these per-channel statistics", OFFSET(measure_perchannel), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, + { "reset", "Set the number of frames over which cumulative stats are calculated before being reset", OFFSET(reset_count), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS }, + { "measure_perchannel", "Select the parameters which are measured per channel", OFFSET(measure_perchannel), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, { "none" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NONE }, 0, 0, FLAGS, "measure" }, { "all" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_ALL }, 0, 0, FLAGS, "measure" }, { "DC_offset" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_DC_OFFSET }, 0, 0, FLAGS, "measure" }, @@ -143,7 +143,7 @@ static const AVOption astats_options[] = { { "Number_of_NaNs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_NANS }, 0, 0, FLAGS, "measure" }, { "Number_of_Infs" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_INFS }, 0, 0, FLAGS, "measure" }, { "Number_of_denormals" , "", 0, AV_OPT_TYPE_CONST, {.i64=MEASURE_NUMBER_OF_DENORMALS }, 0, 0, FLAGS, "measure" }, - { "measure_overall", "only measure_perchannel these overall statistics", OFFSET(measure_overall), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, + { "measure_overall", "Select the parameters which are measured overall", OFFSET(measure_overall), AV_OPT_TYPE_FLAGS, {.i64=MEASURE_ALL}, 0, UINT_MAX, FLAGS, "measure" }, { NULL } }; @@ -403,7 +403,6 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) max_sigma_x = 0, diff1_sum = 0, diff1_sum_x2 = 0, - sigma_x = 0, sigma_x2 = 0, noise_floor = 0, entropy = 0, @@ -428,7 +427,6 @@ static void set_metadata(AudioStatsContext *s, AVDictionary **metadata) diff1_sum_x2 += p->diff1_sum_x2; min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2); max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2); - sigma_x += p->sigma_x; sigma_x2 += p->sigma_x2; noise_floor = FFMAX(noise_floor, p->noise_floor); noise_floor_count += p->noise_floor_count; @@ -659,7 +657,6 @@ static void print_stats(AVFilterContext *ctx) max_sigma_x = 0, diff1_sum_x2 = 0, diff1_sum = 0, - sigma_x = 0, sigma_x2 = 0, noise_floor = 0, entropy = 0, @@ -684,7 +681,6 @@ static void print_stats(AVFilterContext *ctx) diff1_sum += p->diff1_sum; min_sigma_x2 = FFMIN(min_sigma_x2, p->min_sigma_x2); max_sigma_x2 = FFMAX(max_sigma_x2, p->max_sigma_x2); - sigma_x += p->sigma_x; sigma_x2 += p->sigma_x2; noise_floor = FFMAX(noise_floor, p->noise_floor); p->entropy = calc_entropy(s, p); @@ -852,5 +848,5 @@ const AVFilter ff_af_astats = { AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64P, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBLP), - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_atilt.c b/libavfilter/af_atilt.c index a1ce030feb..a6f7782af5 100644 --- a/libavfilter/af_atilt.c +++ b/libavfilter/af_atilt.c @@ -196,7 +196,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } td.in = in; td.out = out; - ctx->internal->execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, + ff_filter_execute(ctx, s->filter_channels, &td, NULL, FFMIN(inlink->channels, ff_filter_get_nb_threads(ctx))); if (out != in) diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index adbae5892d..ee42b2a034 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -99,6 +99,7 @@ enum TransformType { DII, TDII, LATT, + SVF, NB_TTYPE, }; @@ -419,6 +420,54 @@ BIQUAD_LATT_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1) BIQUAD_LATT_FILTER(flt, float, -1., 1., 0) BIQUAD_LATT_FILTER(dbl, double, -1., 1., 0) +#define BIQUAD_SVF_FILTER(name, type, min, max, need_clipping) \ +static void biquad_svf_## name (BiquadsContext *s, \ + const void *input, void *output, int len, \ + double *y0, double *y1, \ + double *unused1, double *unused2, \ + double b0, double b1, double b2, \ + double a1, double a2, int *clippings, \ + int disabled) \ +{ \ + const type *ibuf = input; \ + type *obuf = output; \ + double s0 = *y0; \ + double s1 = *y1; \ + double wet = s->mix; \ + double dry = 1. - wet; \ + double in, out; \ + double t0, t1; \ + \ + for (int i = 0; i < len; i++) { \ + in = ibuf[i]; \ + out = b2 * in + s0; \ + t0 = b0 * in + a1 * s0 + s1; \ + t1 = b1 * in + a2 * s0; \ + s0 = t0; \ + s1 = t1; \ + \ + 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 = s0; \ + *y1 = s1; \ +} + +BIQUAD_SVF_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1) +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) + static void convert_dir2latt(BiquadsContext *s) { double k0, k1, v0, v1, v2; @@ -436,6 +485,24 @@ static void convert_dir2latt(BiquadsContext *s) s->b2 = v2; } +static void convert_dir2svf(BiquadsContext *s) +{ + double a[2]; + double b[3]; + + a[0] = -s->a1; + a[1] = -s->a2; + b[0] = s->b1 - s->a1 * s->b0; + b[1] = s->b2 - s->a2 * s->b0; + b[2] = s->b0; + + s->a1 = a[0]; + s->a2 = a[1]; + s->b0 = b[0]; + s->b1 = b[1]; + s->b2 = b[2]; +} + static int config_filter(AVFilterLink *outlink, int reset) { AVFilterContext *ctx = outlink->src; @@ -724,6 +791,23 @@ static int config_filter(AVFilterLink *outlink, int reset) default: av_assert0(0); } break; + case SVF: + switch (inlink->format) { + case AV_SAMPLE_FMT_S16P: + s->filter = biquad_svf_s16; + break; + case AV_SAMPLE_FMT_S32P: + s->filter = biquad_svf_s32; + break; + case AV_SAMPLE_FMT_FLTP: + s->filter = biquad_svf_flt; + break; + case AV_SAMPLE_FMT_DBLP: + s->filter = biquad_svf_dbl; + break; + default: av_assert0(0); + } + break; default: av_assert0(0); } @@ -732,6 +816,8 @@ static int config_filter(AVFilterLink *outlink, int reset) if (s->transform_type == LATT) convert_dir2latt(s); + else if (s->transform_type == SVF) + convert_dir2svf(s); return 0; } @@ -906,6 +992,7 @@ static const AVOption equalizer_options[] = { {"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"}, @@ -947,6 +1034,7 @@ static const AVOption bass_lowshelf_options[] = { {"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"}, @@ -995,6 +1083,7 @@ static const AVOption treble_highshelf_options[] = { {"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"}, @@ -1042,6 +1131,7 @@ static const AVOption bandpass_options[] = { {"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"}, @@ -1079,6 +1169,7 @@ static const AVOption bandreject_options[] = { {"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"}, @@ -1118,6 +1209,7 @@ static const AVOption lowpass_options[] = { {"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"}, @@ -1157,6 +1249,7 @@ static const AVOption highpass_options[] = { {"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"}, @@ -1196,6 +1289,7 @@ static const AVOption allpass_options[] = { {"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"}, @@ -1228,6 +1322,7 @@ static const AVOption biquad_options[] = { {"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"}, diff --git a/libavfilter/af_drmeter.c b/libavfilter/af_drmeter.c index a4f35b130a..2021cab143 100644 --- a/libavfilter/af_drmeter.c +++ b/libavfilter/af_drmeter.c @@ -26,13 +26,15 @@ #include "avfilter.h" #include "internal.h" +#define BINS 32768 + typedef struct ChannelStats { uint64_t nb_samples; uint64_t blknum; float peak; float sum; - uint32_t peaks[10001]; - uint32_t rms[10001]; + uint32_t peaks[BINS+1]; + uint32_t rms[BINS+1]; } ChannelStats; typedef struct DRMeterContext { @@ -73,8 +75,8 @@ static void finish_block(ChannelStats *p) rms = sqrt(2 * p->sum / p->nb_samples); peak = p->peak; - rms_bin = av_clip(rms * 10000, 0, 10000); - peak_bin = av_clip(peak * 10000, 0, 10000); + rms_bin = av_clip(lrintf(rms * BINS), 0, BINS); + peak_bin = av_clip(lrintf(peak * BINS), 0, BINS); p->rms[rms_bin]++; p->peaks[peak_bin]++; @@ -144,29 +146,29 @@ static void print_stats(AVFilterContext *ctx) finish_block(p); - for (i = 0; i <= 10000; i++) { - if (p->peaks[10000 - i]) { + for (i = 0; i <= BINS; i++) { + if (p->peaks[BINS - i]) { if (first) break; first = 1; } } - secondpeak = (10000 - i) / 10000.; + secondpeak = (BINS - i) / (double)BINS; - for (i = 10000, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { + for (i = BINS, j = 0; i >= 0 && j < 0.2 * p->blknum; i--) { if (p->rms[i]) { - rmssum += SQR(i / 10000.) * p->rms[i]; + rmssum += SQR(i / (double)BINS); j += p->rms[i]; } } chdr = 20 * log10(secondpeak / sqrt(rmssum / (0.2 * p->blknum))); dr += chdr; - av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %.1f\n", ch + 1, chdr); + av_log(ctx, AV_LOG_INFO, "Channel %d: DR: %g\n", ch + 1, chdr); } - av_log(ctx, AV_LOG_INFO, "Overall DR: %.1f\n", dr / s->nb_channels); + av_log(ctx, AV_LOG_INFO, "Overall DR: %g\n", dr / s->nb_channels); } static av_cold void uninit(AVFilterContext *ctx) @@ -200,6 +202,7 @@ const AVFilter ff_af_drmeter = { .priv_size = sizeof(DRMeterContext), .priv_class = &drmeter_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(drmeter_inputs), FILTER_OUTPUTS(drmeter_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_FLT), diff --git a/libavfilter/af_replaygain.c b/libavfilter/af_replaygain.c index 4bf2763bcf..e9bfc5676c 100644 --- a/libavfilter/af_replaygain.c +++ b/libavfilter/af_replaygain.c @@ -428,7 +428,7 @@ static void butter_filter_stereo_samples(ReplayGainContext *s, // (slowing us down). for (j = -4; j < 0; ++j) - if (fabs(hist_a[i + j]) > 1e-10 || fabs(hist_b[i + j]) > 1e-10) + if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f) break; if (!j) { @@ -477,7 +477,7 @@ static void yule_filter_stereo_samples(ReplayGainContext *s, const float *src, // (slowing us down). for (j = -20; j < 0; ++j) - if (fabs(hist_a[i + j]) > 1e-10 || fabs(hist_b[i + j]) > 1e-10) + if (fabsf(hist_a[i + j]) > 1e-10f || fabsf(hist_b[i + j]) > 1e-10f) break; if (!j) { @@ -606,6 +606,7 @@ const AVFilter ff_af_replaygain = { .description = NULL_IF_CONFIG_SMALL("ReplayGain scanner."), .uninit = uninit, .priv_size = sizeof(ReplayGainContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(replaygain_inputs), FILTER_OUTPUTS(replaygain_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c index fa0884bee8..0ba76469de 100644 --- a/libavfilter/af_silencedetect.c +++ b/libavfilter/af_silencedetect.c @@ -272,4 +272,5 @@ const AVFilter ff_af_silencedetect = { AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32P, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P), .priv_class = &silencedetect_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/af_volumedetect.c b/libavfilter/af_volumedetect.c index c137cc7e50..486fccc4e9 100644 --- a/libavfilter/af_volumedetect.c +++ b/libavfilter/af_volumedetect.c @@ -134,6 +134,7 @@ const AVFilter ff_af_volumedetect = { .description = NULL_IF_CONFIG_SMALL("Detect audio volume."), .priv_size = sizeof(VolDetectContext), .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(volumedetect_inputs), FILTER_OUTPUTS(volumedetect_outputs), FILTER_SAMPLEFMTS(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16P), diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index 61cab215bc..5cb3427e98 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; @@ -37,6 +35,8 @@ extern const AVFilter ff_af_adecorrelate; extern const AVFilter ff_af_adelay; extern const AVFilter ff_af_adenorm; extern const AVFilter ff_af_aderivative; +extern const AVFilter ff_af_adynamicequalizer; +extern const AVFilter ff_af_adynamicsmooth; extern const AVFilter ff_af_aecho; extern const AVFilter ff_af_aemphasis; extern const AVFilter ff_af_aeval; @@ -62,6 +62,7 @@ extern const AVFilter ff_af_amix; extern const AVFilter ff_af_amultiply; extern const AVFilter ff_af_anequalizer; extern const AVFilter ff_af_anlmdn; +extern const AVFilter ff_af_anlmf; extern const AVFilter ff_af_anlms; extern const AVFilter ff_af_anull; extern const AVFilter ff_af_apad; @@ -85,6 +86,7 @@ extern const AVFilter ff_af_asettb; extern const AVFilter ff_af_ashowinfo; extern const AVFilter ff_af_asidedata; extern const AVFilter ff_af_asoftclip; +extern const AVFilter ff_af_aspectralstats; extern const AVFilter ff_af_asplit; extern const AVFilter ff_af_asr; extern const AVFilter ff_af_astats; @@ -104,7 +106,6 @@ extern const AVFilter ff_af_bandreject; extern const AVFilter ff_af_bass; extern const AVFilter ff_af_biquad; extern const AVFilter ff_af_bs2b; -extern const AVFilter ff_vf_chromaber_vulkan; extern const AVFilter ff_af_channelmap; extern const AVFilter ff_af_channelsplit; extern const AVFilter ff_af_chorus; @@ -180,11 +181,13 @@ 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_bm3d; extern const AVFilter ff_vf_boxblur; extern const AVFilter ff_vf_boxblur_opencl; extern const AVFilter ff_vf_bwdif; 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_chromanr; @@ -264,6 +267,7 @@ extern const AVFilter ff_vf_fieldmatch; extern const AVFilter ff_vf_fieldorder; extern const AVFilter ff_vf_fillborders; extern const AVFilter ff_vf_find_rect; +extern const AVFilter ff_vf_flip_vulkan; extern const AVFilter ff_vf_floodfill; extern const AVFilter ff_vf_format; extern const AVFilter ff_vf_fps; @@ -275,6 +279,7 @@ extern const AVFilter ff_vf_freezeframes; extern const AVFilter ff_vf_frei0r; extern const AVFilter ff_vf_fspp; extern const AVFilter ff_vf_gblur; +extern const AVFilter ff_vf_gblur_vulkan; extern const AVFilter ff_vf_geq; extern const AVFilter ff_vf_gradfun; extern const AVFilter ff_vf_graphmonitor; @@ -283,6 +288,7 @@ extern const AVFilter ff_vf_greyedge; extern const AVFilter ff_vf_guided; extern const AVFilter ff_vf_haldclut; extern const AVFilter ff_vf_hflip; +extern const AVFilter ff_vf_hflip_vulkan; extern const AVFilter ff_vf_histeq; extern const AVFilter ff_vf_histogram; extern const AVFilter ff_vf_hqdn3d; @@ -291,6 +297,7 @@ extern const AVFilter ff_vf_hstack; extern const AVFilter ff_vf_hsvhold; extern const AVFilter ff_vf_hsvkey; extern const AVFilter ff_vf_hue; +extern const AVFilter ff_vf_huesaturation; extern const AVFilter ff_vf_hwdownload; extern const AVFilter ff_vf_hwmap; extern const AVFilter ff_vf_hwupload; @@ -308,6 +315,7 @@ extern const AVFilter ff_vf_lagfun; extern const AVFilter ff_vf_latency; extern const AVFilter ff_vf_lenscorrection; extern const AVFilter ff_vf_lensfun; +extern const AVFilter ff_vf_libplacebo; extern const AVFilter ff_vf_libvmaf; extern const AVFilter ff_vf_limitdiff; extern const AVFilter ff_vf_limiter; @@ -397,6 +405,7 @@ extern const AVFilter ff_vf_scale_qsv; extern const AVFilter ff_vf_scale_vaapi; extern const AVFilter ff_vf_scale_vulkan; extern const AVFilter ff_vf_scale2ref; +extern const AVFilter ff_vf_scale2ref_npp; extern const AVFilter ff_vf_scdet; extern const AVFilter ff_vf_scharr; extern const AVFilter ff_vf_scroll; @@ -456,6 +465,7 @@ extern const AVFilter ff_vf_transpose; extern const AVFilter ff_vf_transpose_npp; extern const AVFilter ff_vf_transpose_opencl; extern const AVFilter ff_vf_transpose_vaapi; +extern const AVFilter ff_vf_transpose_vulkan; extern const AVFilter ff_vf_trim; extern const AVFilter ff_vf_unpremultiply; extern const AVFilter ff_vf_unsharp; @@ -467,6 +477,7 @@ extern const AVFilter ff_vf_vaguedenoiser; extern const AVFilter ff_vf_varblur; extern const AVFilter ff_vf_vectorscope; extern const AVFilter ff_vf_vflip; +extern const AVFilter ff_vf_vflip_vulkan; extern const AVFilter ff_vf_vfrdet; extern const AVFilter ff_vf_vibrance; extern const AVFilter ff_vf_vidstabdetect; @@ -487,6 +498,7 @@ extern const AVFilter ff_vf_xmedian; extern const AVFilter ff_vf_xstack; extern const AVFilter ff_vf_yadif; extern const AVFilter ff_vf_yadif_cuda; +extern const AVFilter ff_vf_yadif_videotoolbox; extern const AVFilter ff_vf_yaepblur; extern const AVFilter ff_vf_zmq; extern const AVFilter ff_vf_zoompan; @@ -496,6 +508,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_colorspectrum; extern const AVFilter ff_vsrc_coreimagesrc; extern const AVFilter ff_vsrc_frei0r_src; extern const AVFilter ff_vsrc_gradients; diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index f7208754a7..b105dc3159 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -119,6 +119,22 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx); * and processing them concurrently. */ #define AVFILTER_FLAG_SLICE_THREADS (1 << 2) +/** + * The filter is a "metadata" filter - it does not modify the frame data in any + * way. It may only affect the metadata (i.e. those fields copied by + * av_frame_copy_props()). + * + * More precisely, this means: + * - video: the data of any frame output by the filter must be exactly equal to + * some frame that is received on one of its inputs. Furthermore, all frames + * produced on a given output must correspond to frames received on the same + * input and their order must be unchanged. Note that the filter may still + * drop or duplicate the frames. + * - audio: the data produced by the filter on any of its outputs (viewed e.g. + * as an array of interleaved samples) must be exactly equal to the data + * received by the filter on one of its inputs. + */ +#define AVFILTER_FLAG_METADATA_ONLY (1 << 3) /** * Some filters support a generic "enable" expression option that can be used * to enable or disable a filter in the timeline. Filters supporting this diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index b8ddafec35..c0215669e7 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -43,18 +43,18 @@ typedef struct BufferSinkContext { unsigned warning_limit; /* only used for video */ - enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats, must be terminated with -1 + enum AVPixelFormat *pixel_fmts; ///< list of accepted pixel formats int pixel_fmts_size; /* only used for audio */ - enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats, terminated by AV_SAMPLE_FMT_NONE + enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats int sample_fmts_size; - int64_t *channel_layouts; ///< list of accepted channel layouts, terminated by -1 + int64_t *channel_layouts; ///< list of accepted channel layouts int channel_layouts_size; - int *channel_counts; ///< list of accepted channel counts, terminated by -1 + int *channel_counts; ///< list of accepted channel counts int channel_counts_size; int all_channel_counts; - int *sample_rates; ///< list of accepted sample rates, terminated by -1 + int *sample_rates; ///< list of accepted sample rates int sample_rates_size; AVFrame *peeked_frame; diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c index 88218b913f..65ed61aa92 100644 --- a/libavfilter/drawutils.c +++ b/libavfilter/drawutils.c @@ -21,6 +21,7 @@ #include +#include "libavutil/avassert.h" #include "libavutil/avutil.h" #include "libavutil/colorspace.h" #include "libavutil/intreadwrite.h" @@ -32,50 +33,46 @@ enum { RED = 0, GREEN, BLUE, ALPHA }; int ff_fill_rgba_map(uint8_t *rgba_map, enum AVPixelFormat pix_fmt) { - switch (pix_fmt) { - case AV_PIX_FMT_0RGB: - case AV_PIX_FMT_ARGB: rgba_map[ALPHA] = 0; rgba_map[RED ] = 1; rgba_map[GREEN] = 2; rgba_map[BLUE ] = 3; break; - case AV_PIX_FMT_0BGR: - case AV_PIX_FMT_ABGR: rgba_map[ALPHA] = 0; rgba_map[BLUE ] = 1; rgba_map[GREEN] = 2; rgba_map[RED ] = 3; break; - case AV_PIX_FMT_RGB48LE: - case AV_PIX_FMT_RGB48BE: - case AV_PIX_FMT_RGBA64BE: - case AV_PIX_FMT_RGBA64LE: - case AV_PIX_FMT_RGB0: - case AV_PIX_FMT_RGBA: - case AV_PIX_FMT_RGB24: rgba_map[RED ] = 0; rgba_map[GREEN] = 1; rgba_map[BLUE ] = 2; rgba_map[ALPHA] = 3; break; - case AV_PIX_FMT_BGR48LE: - case AV_PIX_FMT_BGR48BE: - case AV_PIX_FMT_BGRA64BE: - case AV_PIX_FMT_BGRA64LE: - case AV_PIX_FMT_BGRA: - case AV_PIX_FMT_BGR0: - case AV_PIX_FMT_BGR24: rgba_map[BLUE ] = 0; rgba_map[GREEN] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; - case AV_PIX_FMT_GBRP9LE: - case AV_PIX_FMT_GBRP9BE: - case AV_PIX_FMT_GBRP10LE: - case AV_PIX_FMT_GBRP10BE: - case AV_PIX_FMT_GBRP12LE: - case AV_PIX_FMT_GBRP12BE: - case AV_PIX_FMT_GBRP14LE: - case AV_PIX_FMT_GBRP14BE: - case AV_PIX_FMT_GBRP16LE: - case AV_PIX_FMT_GBRP16BE: - case AV_PIX_FMT_GBRAP: - case AV_PIX_FMT_GBRAP10LE: - case AV_PIX_FMT_GBRAP10BE: - case AV_PIX_FMT_GBRAP12LE: - case AV_PIX_FMT_GBRAP12BE: - case AV_PIX_FMT_GBRAP16LE: - case AV_PIX_FMT_GBRAP16BE: - case AV_PIX_FMT_GBRPF32LE: - case AV_PIX_FMT_GBRPF32BE: - case AV_PIX_FMT_GBRAPF32LE: - case AV_PIX_FMT_GBRAPF32BE: - case AV_PIX_FMT_GBRP: rgba_map[GREEN] = 0; rgba_map[BLUE ] = 1; rgba_map[RED ] = 2; rgba_map[ALPHA] = 3; break; - default: /* unsupported */ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) return AVERROR(EINVAL); + if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) + return AVERROR(EINVAL); + av_assert0(desc->nb_components == 3 + !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)); + if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) { + rgba_map[RED] = desc->comp[0].plane; + rgba_map[GREEN] = desc->comp[1].plane; + rgba_map[BLUE] = desc->comp[2].plane; + rgba_map[ALPHA] = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? desc->comp[3].plane : 3; + } else { + int had0 = 0; + unsigned depthb = 0; + unsigned i; + for (i = 0; i < desc->nb_components; i++) { + /* all components must have same depth in bytes */ + unsigned db = (desc->comp[i].depth + 7) / 8; + unsigned pos = desc->comp[i].offset / db; + if (depthb && (depthb != db)) + return AVERROR(ENOSYS); + + if (desc->comp[i].offset % db) + return AVERROR(ENOSYS); + + had0 |= pos == 0; + rgba_map[i] = pos; + } + + if (desc->nb_components == 3) + rgba_map[ALPHA] = had0 ? 3 : 0; } + + av_assert0(rgba_map[RED] != rgba_map[GREEN]); + av_assert0(rgba_map[GREEN] != rgba_map[BLUE]); + av_assert0(rgba_map[BLUE] != rgba_map[RED]); + av_assert0(rgba_map[RED] != rgba_map[ALPHA]); + av_assert0(rgba_map[GREEN] != rgba_map[ALPHA]); + av_assert0(rgba_map[BLUE] != rgba_map[ALPHA]); + return 0; } @@ -86,25 +83,37 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) unsigned i, nb_planes = 0; int pixelstep[MAX_PLANES] = { 0 }; int full_range = 0; + int depthb = 0; if (!desc || !desc->name) return AVERROR(EINVAL); - if (desc->flags & ~(AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA)) + if (desc->flags & AV_PIX_FMT_FLAG_BE) return AVERROR(ENOSYS); - if (format == AV_PIX_FMT_P010LE || format == AV_PIX_FMT_P010BE || format == AV_PIX_FMT_P016LE || format == AV_PIX_FMT_P016BE) + 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; for (i = 0; i < desc->nb_components; i++) { + int db; c = &desc->comp[i]; /* for now, only 8-16 bits formats */ if (c->depth < 8 || c->depth > 16) return AVERROR(ENOSYS); - if (desc->flags & AV_PIX_FMT_FLAG_BE) - return AVERROR(ENOSYS); if (c->plane >= MAX_PLANES) return AVERROR(ENOSYS); + /* data must either be in the high or low bits, never middle */ + if (c->shift && ((c->shift + c->depth) & 0x7)) + return AVERROR(ENOSYS); + /* mixed >8 and <=8 depth */ + db = (c->depth + 7) / 8; + if (depthb && (depthb != db)) + return AVERROR(ENOSYS); + depthb = db; + if (db * (c->offset + 1) > 16) + return AVERROR(ENOSYS); + if (c->offset % db) + return AVERROR(ENOSYS); /* strange interleaving */ if (pixelstep[c->plane] != 0 && pixelstep[c->plane] != c->step) @@ -126,66 +135,49 @@ int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags) 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; - for (i = 0; i < (desc->nb_components - !!(desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(flags & FF_DRAW_PROCESS_ALPHA))); i++) - draw->comp_mask[desc->comp[i].plane] |= - 1 << desc->comp[i].offset; return 0; } void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4]) { unsigned i; - uint8_t rgba_map[4]; + uint8_t tmp8[4]; + const AVPixFmtDescriptor *desc = draw->desc; if (rgba != color->rgba) memcpy(color->rgba, rgba, sizeof(color->rgba)); - if ((draw->desc->flags & AV_PIX_FMT_FLAG_RGB) && - ff_fill_rgba_map(rgba_map, draw->format) >= 0) { - if (draw->nb_planes == 1) { - for (i = 0; i < 4; i++) { - color->comp[0].u8[rgba_map[i]] = rgba[i]; - if (draw->desc->comp[rgba_map[i]].depth > 8) { - color->comp[0].u16[rgba_map[i]] = color->comp[0].u8[rgba_map[i]] << 8; - } - } - } else { - for (i = 0; i < 4; i++) { - color->comp[rgba_map[i]].u8[0] = rgba[i]; - if (draw->desc->comp[rgba_map[i]].depth > 8) - color->comp[rgba_map[i]].u16[0] = color->comp[rgba_map[i]].u8[0] << (draw->desc->comp[rgba_map[i]].depth - 8); - } - } + + 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 */ - const AVPixFmtDescriptor *desc = draw->desc; - color->comp[desc->comp[0].plane].u8[desc->comp[0].offset] = draw->full_range ? RGB_TO_Y_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - color->comp[desc->comp[1].plane].u8[desc->comp[1].offset] = draw->full_range ? RGB_TO_U_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_U_CCIR(rgba[0], rgba[1], rgba[2], 0); - color->comp[desc->comp[2].plane].u8[desc->comp[2].offset] = draw->full_range ? RGB_TO_V_JPEG(rgba[0], rgba[1], rgba[2]) : RGB_TO_V_CCIR(rgba[0], rgba[1], rgba[2], 0); - color->comp[3].u8[0] = rgba[3]; -#define EXPAND(compn) \ - if (desc->comp[compn].depth > 8) \ - color->comp[desc->comp[compn].plane].u16[desc->comp[compn].offset] = \ - color->comp[desc->comp[compn].plane].u8[desc->comp[compn].offset] << \ - (draw->desc->comp[compn].depth + draw->desc->comp[compn].shift - 8) - EXPAND(3); - EXPAND(2); - EXPAND(1); - EXPAND(0); + 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) { - const AVPixFmtDescriptor *desc = draw->desc; - color->comp[0].u8[0] = RGB_TO_Y_CCIR(rgba[0], rgba[1], rgba[2]); - EXPAND(0); - color->comp[1].u8[0] = rgba[3]; - EXPAND(1); + 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 (i = 0; i < desc->nb_components; i++) { + 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); + else + color->comp[desc->comp[i].plane].u8[desc->comp[i].offset] = tmp8[i]; } } @@ -291,11 +283,6 @@ static void subsampling_bounds(int sub, int *x, int *w, int *start, int *end) *w >>= sub; } -static int component_used(FFDrawContext *draw, int plane, int comp) -{ - return (draw->comp_mask[plane] >> comp) & 1; -} - /* If alpha is in the [ 0 ; 0x1010101 ] range, then alpha * value is in the [ 0 ; 0xFFFFFFFF ] range, and >> 24 gives a correct rounding. */ @@ -355,6 +342,9 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, int w_sub, h_sub, x_sub, y_sub, left, right, top, bottom, y; uint8_t *p0, *p; + nb_comp = draw->desc->nb_components - + !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); + /* TODO optimize if alpha = 0xFF */ clip_interval(dst_w, &x0, &w, NULL); clip_interval(dst_h, &y0, &h, NULL); @@ -370,7 +360,6 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); nb_planes += !nb_planes; for (plane = 0; plane < nb_planes; plane++) { - nb_comp = draw->pixelstep[plane]; p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); w_sub = w; h_sub = h; @@ -380,17 +369,19 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); for (comp = 0; comp < nb_comp; comp++) { const int depth = draw->desc->comp[comp].depth; + const int offset = draw->desc->comp[comp].offset; + const int index = offset / ((depth + 7) / 8); - if (!component_used(draw, plane, comp)) + if (draw->desc->comp[comp].plane != plane) continue; - p = p0 + comp; + p = p0 + offset; if (top) { if (depth <= 8) { - blend_line(p, color->comp[plane].u8[comp], alpha >> 1, + blend_line(p, color->comp[plane].u8[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } else { - blend_line16(p, color->comp[plane].u16[comp], alpha >> 1, + blend_line16(p, color->comp[plane].u16[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } @@ -398,14 +389,14 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, } if (depth <= 8) { for (y = 0; y < h_sub; y++) { - blend_line(p, color->comp[plane].u8[comp], alpha, + blend_line(p, color->comp[plane].u8[index], alpha, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); p += dst_linesize[plane]; } } else { for (y = 0; y < h_sub; y++) { - blend_line16(p, color->comp[plane].u16[comp], alpha, + blend_line16(p, color->comp[plane].u16[index], alpha, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); p += dst_linesize[plane]; @@ -413,11 +404,11 @@ void ff_blend_rectangle(FFDrawContext *draw, FFDrawColor *color, } if (bottom) { if (depth <= 8) { - blend_line(p, color->comp[plane].u8[comp], alpha >> 1, + blend_line(p, color->comp[plane].u8[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } else { - blend_line16(p, color->comp[plane].u16[comp], alpha >> 1, + blend_line16(p, color->comp[plane].u16[index], alpha >> 1, draw->pixelstep[plane], w_sub, draw->hsub[plane], left, right); } @@ -533,6 +524,9 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, uint8_t *p0, *p; const uint8_t *m; + nb_comp = draw->desc->nb_components - + !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); + clip_interval(dst_w, &x0, &mask_w, &xm0); clip_interval(dst_h, &y0, &mask_h, &ym0); mask += ym0 * mask_linesize; @@ -548,7 +542,6 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, nb_planes = draw->nb_planes - !!(draw->desc->flags & AV_PIX_FMT_FLAG_ALPHA && !(draw->flags & FF_DRAW_PROCESS_ALPHA)); nb_planes += !nb_planes; for (plane = 0; plane < nb_planes; plane++) { - nb_comp = draw->pixelstep[plane]; p0 = pointer_at(draw, dst, dst_linesize, plane, x0, y0); w_sub = mask_w; h_sub = mask_h; @@ -558,21 +551,23 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, subsampling_bounds(draw->vsub[plane], &y_sub, &h_sub, &top, &bottom); for (comp = 0; comp < nb_comp; comp++) { const int depth = draw->desc->comp[comp].depth; + const int offset = draw->desc->comp[comp].offset; + const int index = offset / ((depth + 7) / 8); - if (!component_used(draw, plane, comp)) + if (draw->desc->comp[comp].plane != plane) continue; - p = p0 + comp; + p = p0 + offset; m = mask; if (top) { if (depth <= 8) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, top); } else { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, top); @@ -583,7 +578,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, if (depth <= 8) { for (y = 0; y < h_sub; y++) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, 1 << draw->vsub[plane]); @@ -593,7 +588,7 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, } else { for (y = 0; y < h_sub; y++) { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, 1 << draw->vsub[plane]); @@ -604,13 +599,13 @@ void ff_blend_mask(FFDrawContext *draw, FFDrawColor *color, if (bottom) { if (depth <= 8) { blend_line_hv(p, draw->pixelstep[plane], - color->comp[plane].u8[comp], alpha, + color->comp[plane].u8[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, bottom); } else { blend_line_hv16(p, draw->pixelstep[plane], - color->comp[plane].u16[comp], alpha, + color->comp[plane].u16[index], alpha, m, mask_linesize, l2depth, w_sub, draw->hsub[plane], draw->vsub[plane], xm0, left, right, bottom); diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h index 2ca2475585..396688514e 100644 --- a/libavfilter/drawutils.h +++ b/libavfilter/drawutils.h @@ -37,7 +37,6 @@ typedef struct FFDrawContext { enum AVPixelFormat format; unsigned nb_planes; int pixelstep[MAX_PLANES]; /*< offset between pixels */ - uint8_t comp_mask[MAX_PLANES]; /*< bitmask of used non-alpha components */ uint8_t hsub[MAX_PLANES]; /*< horizontal subsampling */ uint8_t vsub[MAX_PLANES]; /*< vertical subsampling */ uint8_t hsub_max; diff --git a/libavfilter/f_bench.c b/libavfilter/f_bench.c index f7098adaf4..109a530d7c 100644 --- a/libavfilter/f_bench.c +++ b/libavfilter/f_bench.c @@ -113,6 +113,7 @@ const AVFilter ff_vf_bench = { FILTER_INPUTS(bench_inputs), FILTER_OUTPUTS(bench_outputs), .priv_class = &bench_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_BENCH_FILTER */ @@ -143,5 +144,6 @@ const AVFilter ff_af_abench = { FILTER_INPUTS(abench_inputs), FILTER_OUTPUTS(abench_outputs), .priv_class = &abench_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ABENCH_FILTER */ diff --git a/libavfilter/f_cue.c b/libavfilter/f_cue.c index fd55e4bf5f..d90fe54b9a 100644 --- a/libavfilter/f_cue.c +++ b/libavfilter/f_cue.c @@ -142,6 +142,7 @@ const AVFilter ff_af_acue = { .description = NULL_IF_CONFIG_SMALL("Delay filtering to match a cue."), .priv_class = &cue_acue_class, .priv_size = sizeof(CueContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(acue_inputs), FILTER_OUTPUTS(acue_outputs), .activate = activate, diff --git a/libavfilter/f_latency.c b/libavfilter/f_latency.c index de885ca026..6f16d6677e 100644 --- a/libavfilter/f_latency.c +++ b/libavfilter/f_latency.c @@ -118,7 +118,8 @@ const AVFilter ff_vf_latency = { .init = init, .uninit = uninit, .activate = activate, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(latency_inputs), FILTER_OUTPUTS(latency_outputs), }; diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c index cecfe62a9c..5f5091e9b7 100644 --- a/libavfilter/f_metadata.c +++ b/libavfilter/f_metadata.c @@ -391,7 +391,8 @@ const AVFilter ff_af_ametadata = { .uninit = uninit, FILTER_INPUTS(ainputs), FILTER_OUTPUTS(aoutputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_AMETADATA_FILTER */ @@ -424,6 +425,7 @@ const AVFilter ff_vf_metadata = { .uninit = uninit, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_METADATA_FILTER */ diff --git a/libavfilter/f_perms.c b/libavfilter/f_perms.c index 470db45bee..6e75b2517b 100644 --- a/libavfilter/f_perms.c +++ b/libavfilter/f_perms.c @@ -138,7 +138,8 @@ const AVFilter ff_af_aperms = { .priv_size = sizeof(PermsContext), FILTER_INPUTS(aperms_inputs), FILTER_OUTPUTS(aperms_outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_APERMS_FILTER */ @@ -167,6 +168,7 @@ const AVFilter ff_vf_perms = { FILTER_INPUTS(perms_inputs), FILTER_OUTPUTS(perms_outputs), .priv_class = &perms_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_PERMS_FILTER */ diff --git a/libavfilter/f_realtime.c b/libavfilter/f_realtime.c index 11bdb058ed..9a60ded0ca 100644 --- a/libavfilter/f_realtime.c +++ b/libavfilter/f_realtime.c @@ -95,6 +95,7 @@ const AVFilter ff_vf_realtime = { .description = NULL_IF_CONFIG_SMALL("Slow down filtering to match realtime."), .priv_size = sizeof(RealtimeContext), .priv_class = &realtime_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_realtime_inputs), FILTER_OUTPUTS(avfilter_vf_realtime_outputs), }; @@ -122,6 +123,7 @@ const AVFilter ff_af_arealtime = { .description = NULL_IF_CONFIG_SMALL("Slow down filtering to match realtime."), .priv_class = &realtime_class, .priv_size = sizeof(RealtimeContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(arealtime_inputs), FILTER_OUTPUTS(arealtime_outputs), }; diff --git a/libavfilter/f_reverse.c b/libavfilter/f_reverse.c index 586d95c063..f7a7e716fa 100644 --- a/libavfilter/f_reverse.c +++ b/libavfilter/f_reverse.c @@ -33,6 +33,7 @@ typedef struct ReverseContext { unsigned int pts_size; int64_t *pts; int flush_idx; + int64_t nb_samples; } ReverseContext; static av_cold int init(AVFilterContext *ctx) @@ -249,7 +250,8 @@ static int areverse_request_frame(AVFilterLink *outlink) if (ret == AVERROR_EOF && s->nb_frames > 0) { AVFrame *out = s->frames[s->nb_frames - 1]; - out->pts = s->pts[s->flush_idx++]; + out->pts = s->pts[s->flush_idx++] - s->nb_samples; + s->nb_samples += s->pts[s->flush_idx] - s->pts[s->flush_idx - 1] - out->nb_samples; if (av_sample_fmt_is_planar(out->format)) reverse_samples_planar(out); diff --git a/libavfilter/f_segment.c b/libavfilter/f_segment.c index 70c8393972..5f44634803 100644 --- a/libavfilter/f_segment.c +++ b/libavfilter/f_segment.c @@ -286,7 +286,7 @@ const AVFilter ff_vf_segment = { .activate = activate, FILTER_INPUTS(segment_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif // CONFIG_SEGMENT_FILTER @@ -325,6 +325,6 @@ const AVFilter ff_af_asegment = { .activate = activate, FILTER_INPUTS(asegment_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif // CONFIG_ASEGMENT_FILTER diff --git a/libavfilter/f_select.c b/libavfilter/f_select.c index 47e7d1fef8..b61d88f4fe 100644 --- a/libavfilter/f_select.c +++ b/libavfilter/f_select.c @@ -533,6 +533,6 @@ const AVFilter ff_vf_select = { .priv_class = &select_class, FILTER_INPUTS(avfilter_vf_select_inputs), FILTER_QUERY_FUNC(query_formats), - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SELECT_FILTER */ diff --git a/libavfilter/f_sendcmd.c b/libavfilter/f_sendcmd.c index f71d211eb4..7261a05aae 100644 --- a/libavfilter/f_sendcmd.c +++ b/libavfilter/f_sendcmd.c @@ -597,6 +597,7 @@ const AVFilter ff_vf_sendcmd = { .init = init, .uninit = uninit, .priv_size = sizeof(SendCmdContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(sendcmd_inputs), FILTER_OUTPUTS(sendcmd_outputs), .priv_class = &sendcmd_class, @@ -628,6 +629,7 @@ const AVFilter ff_af_asendcmd = { .init = init, .uninit = uninit, .priv_size = sizeof(SendCmdContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asendcmd_inputs), FILTER_OUTPUTS(asendcmd_outputs), }; diff --git a/libavfilter/f_sidedata.c b/libavfilter/f_sidedata.c index 5c9f905cc2..8eccd4a06e 100644 --- a/libavfilter/f_sidedata.c +++ b/libavfilter/f_sidedata.c @@ -147,7 +147,8 @@ const AVFilter ff_af_asidedata = { .init = init, FILTER_INPUTS(ainputs), FILTER_OUTPUTS(aoutputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ASIDEDATA_FILTER */ @@ -179,6 +180,7 @@ const AVFilter ff_vf_sidedata = { .init = init, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SIDEDATA_FILTER */ diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c index bb7d78f09c..1c7be88ae1 100644 --- a/libavfilter/fifo.c +++ b/libavfilter/fifo.c @@ -132,6 +132,7 @@ const AVFilter ff_vf_fifo = { .init = init, .uninit = uninit, .priv_size = sizeof(FifoContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_fifo_inputs), FILTER_OUTPUTS(avfilter_vf_fifo_outputs), }; @@ -158,6 +159,7 @@ const AVFilter ff_af_afifo = { .init = init, .uninit = uninit, .priv_size = sizeof(FifoContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_af_afifo_inputs), FILTER_OUTPUTS(avfilter_af_afifo_outputs), }; diff --git a/libavfilter/glslang.cpp b/libavfilter/glslang.cpp deleted file mode 100644 index 986bddd789..0000000000 --- a/libavfilter/glslang.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include - -extern "C" { -#include "libavutil/mem.h" -#include "libavutil/avassert.h" -} - -#include -#include -#include - -#include "glslang.h" - -using namespace glslang; - -static pthread_mutex_t glslang_mutex = PTHREAD_MUTEX_INITIALIZER; -static int glslang_refcount = 0; - -/* We require Vulkan 1.1 */ -#define GLSL_VERSION EShTargetVulkan_1_1 - -/* Vulkan 1.1 implementations require SPIR-V 1.3 to be implemented */ -#define SPIRV_VERSION EShTargetSpv_1_3 - -// Taken from glslang's examples, which apparently generally bases the choices -// on OpenGL specification limits -static const TBuiltInResource DefaultTBuiltInResource = { - /* .MaxLights = */ 32, - /* .MaxClipPlanes = */ 6, - /* .MaxTextureUnits = */ 32, - /* .MaxTextureCoords = */ 32, - /* .MaxVertexAttribs = */ 64, - /* .MaxVertexUniformComponents = */ 4096, - /* .MaxVaryingFloats = */ 64, - /* .MaxVertexTextureImageUnits = */ 32, - /* .MaxCombinedTextureImageUnits = */ 80, - /* .MaxTextureImageUnits = */ 32, - /* .MaxFragmentUniformComponents = */ 4096, - /* .MaxDrawBuffers = */ 32, - /* .MaxVertexUniformVectors = */ 128, - /* .MaxVaryingVectors = */ 8, - /* .MaxFragmentUniformVectors = */ 16, - /* .MaxVertexOutputVectors = */ 16, - /* .MaxFragmentInputVectors = */ 15, - /* .MinProgramTexelOffset = */ -8, - /* .MaxProgramTexelOffset = */ 7, - /* .MaxClipDistances = */ 8, - /* .MaxComputeWorkGroupCountX = */ 65535, - /* .MaxComputeWorkGroupCountY = */ 65535, - /* .MaxComputeWorkGroupCountZ = */ 65535, - /* .MaxComputeWorkGroupSizeX = */ 1024, - /* .MaxComputeWorkGroupSizeY = */ 1024, - /* .MaxComputeWorkGroupSizeZ = */ 64, - /* .MaxComputeUniformComponents = */ 1024, - /* .MaxComputeTextureImageUnits = */ 16, - /* .MaxComputeImageUniforms = */ 8, - /* .MaxComputeAtomicCounters = */ 8, - /* .MaxComputeAtomicCounterBuffers = */ 1, - /* .MaxVaryingComponents = */ 60, - /* .MaxVertexOutputComponents = */ 64, - /* .MaxGeometryInputComponents = */ 64, - /* .MaxGeometryOutputComponents = */ 128, - /* .MaxFragmentInputComponents = */ 128, - /* .MaxImageUnits = */ 8, - /* .MaxCombinedImageUnitsAndFragmentOutputs = */ 8, - /* .MaxCombinedShaderOutputResources = */ 8, - /* .MaxImageSamples = */ 0, - /* .MaxVertexImageUniforms = */ 0, - /* .MaxTessControlImageUniforms = */ 0, - /* .MaxTessEvaluationImageUniforms = */ 0, - /* .MaxGeometryImageUniforms = */ 0, - /* .MaxFragmentImageUniforms = */ 8, - /* .MaxCombinedImageUniforms = */ 8, - /* .MaxGeometryTextureImageUnits = */ 16, - /* .MaxGeometryOutputVertices = */ 256, - /* .MaxGeometryTotalOutputComponents = */ 1024, - /* .MaxGeometryUniformComponents = */ 1024, - /* .MaxGeometryVaryingComponents = */ 64, - /* .MaxTessControlInputComponents = */ 128, - /* .MaxTessControlOutputComponents = */ 128, - /* .MaxTessControlTextureImageUnits = */ 16, - /* .MaxTessControlUniformComponents = */ 1024, - /* .MaxTessControlTotalOutputComponents = */ 4096, - /* .MaxTessEvaluationInputComponents = */ 128, - /* .MaxTessEvaluationOutputComponents = */ 128, - /* .MaxTessEvaluationTextureImageUnits = */ 16, - /* .MaxTessEvaluationUniformComponents = */ 1024, - /* .MaxTessPatchComponents = */ 120, - /* .MaxPatchVertices = */ 32, - /* .MaxTessGenLevel = */ 64, - /* .MaxViewports = */ 16, - /* .MaxVertexAtomicCounters = */ 0, - /* .MaxTessControlAtomicCounters = */ 0, - /* .MaxTessEvaluationAtomicCounters = */ 0, - /* .MaxGeometryAtomicCounters = */ 0, - /* .MaxFragmentAtomicCounters = */ 8, - /* .MaxCombinedAtomicCounters = */ 8, - /* .MaxAtomicCounterBindings = */ 1, - /* .MaxVertexAtomicCounterBuffers = */ 0, - /* .MaxTessControlAtomicCounterBuffers = */ 0, - /* .MaxTessEvaluationAtomicCounterBuffers = */ 0, - /* .MaxGeometryAtomicCounterBuffers = */ 0, - /* .MaxFragmentAtomicCounterBuffers = */ 1, - /* .MaxCombinedAtomicCounterBuffers = */ 1, - /* .MaxAtomicCounterBufferSize = */ 16384, - /* .MaxTransformFeedbackBuffers = */ 4, - /* .MaxTransformFeedbackInterleavedComponents = */ 64, - /* .MaxCullDistances = */ 8, - /* .MaxCombinedClipAndCullDistances = */ 8, - /* .MaxSamples = */ 4, - /* .maxMeshOutputVerticesNV = */ 256, - /* .maxMeshOutputPrimitivesNV = */ 512, - /* .maxMeshWorkGroupSizeX_NV = */ 32, - /* .maxMeshWorkGroupSizeY_NV = */ 1, - /* .maxMeshWorkGroupSizeZ_NV = */ 1, - /* .maxTaskWorkGroupSizeX_NV = */ 32, - /* .maxTaskWorkGroupSizeY_NV = */ 1, - /* .maxTaskWorkGroupSizeZ_NV = */ 1, - /* .maxMeshViewCountNV = */ 4, - - .limits = { - /* .nonInductiveForLoops = */ 1, - /* .whileLoops = */ 1, - /* .doWhileLoops = */ 1, - /* .generalUniformIndexing = */ 1, - /* .generalAttributeMatrixVectorIndexing = */ 1, - /* .generalVaryingIndexing = */ 1, - /* .generalSamplerIndexing = */ 1, - /* .generalVariableIndexing = */ 1, - /* .generalConstantMatrixVectorIndexing = */ 1, - } -}; - -GLSlangResult *glslang_compile(const char *glsl, enum GLSlangStage stage) -{ - GLSlangResult *res = (GLSlangResult *)av_mallocz(sizeof(*res)); - if (!res) - return NULL; - - static const EShLanguage lang[] = { - [GLSLANG_VERTEX] = EShLangVertex, - [GLSLANG_FRAGMENT] = EShLangFragment, - [GLSLANG_COMPUTE] = EShLangCompute, - }; - - assert(glslang_refcount); - TShader *shader = new TShader(lang[stage]); - if (!shader) { - res->rval = AVERROR(ENOMEM); - return res; - } - - shader->setEnvClient(EShClientVulkan, GLSL_VERSION); - shader->setEnvTarget(EShTargetSpv, SPIRV_VERSION); - shader->setStrings(&glsl, 1); - if (!shader->parse(&DefaultTBuiltInResource, GLSL_VERSION, true, EShMsgDefault)) { - res->error_msg = av_strdup(shader->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - return res; - } - - TProgram *prog = new TProgram(); - if (!prog) { - res->rval = AVERROR(ENOMEM); - delete shader; - return res; - } - - prog->addShader(shader); - if (!prog->link(EShMsgDefault)) { - res->error_msg = av_strdup(prog->getInfoLog()); - res->rval = AVERROR_EXTERNAL; - delete shader; - delete prog; - return res; - } - - std::vector spirv; /* Result */ - - SpvOptions options; /* Options - by default all optimizations are off */ - options.generateDebugInfo = false; /* Makes sense for files but not here */ - options.disassemble = false; /* Will print disassembly on compilation */ - options.validate = false; /* Validates the generated SPIRV, unneeded */ - options.disableOptimizer = false; /* For debugging */ - options.optimizeSize = true; /* Its faster */ - - GlslangToSpv(*prog->getIntermediate(lang[stage]), spirv, NULL, &options); - - res->size = spirv.size()*sizeof(unsigned int); - res->data = av_memdup(spirv.data(), res->size); - if (!res->data) { - res->rval = AVERROR(ENOMEM); - delete shader; - delete prog; - return res; - } - - delete shader; - delete prog; - - return res; -} - -int glslang_init(void) -{ - int ret = 0; - - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount++ == 0) - ret = !InitializeProcess(); - pthread_mutex_unlock(&glslang_mutex); - - return ret; -} - -void glslang_uninit(void) -{ - pthread_mutex_lock(&glslang_mutex); - if (glslang_refcount && (--glslang_refcount == 0)) - FinalizeProcess(); - pthread_mutex_unlock(&glslang_mutex); -} diff --git a/libavfilter/metal/utils.h b/libavfilter/metal/utils.h new file mode 100644 index 0000000000..7350d42a35 --- /dev/null +++ b/libavfilter/metal/utils.h @@ -0,0 +1,59 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_METAL_UTILS_H +#define AVFILTER_METAL_UTILS_H + +#include + +#include + +// CoreVideo accidentally(?) preprocessor-gates Metal functionality +// on MAC_OS_X_VERSION_MIN_REQUIRED >= 101100 (FB9816002). +// There doesn't seem to be any particular reason for this, +// so here we temporarily redefine it to at least that value +// so CV will give us CVMetalTextureRef and the related functions. + +#if defined(MAC_OS_X_VERSION_MIN_REQUIRED) && (MAC_OS_X_VERSION_MIN_REQUIRED < 101100) +#define ORIG_MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#define MAC_OS_X_VERSION_MIN_REQUIRED 101100 +#endif + +#include + +#ifdef ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#undef MAC_OS_X_VERSION_MIN_REQUIRED +#define MAC_OS_X_VERSION_MIN_REQUIRED ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#undef ORIG_MAC_OS_X_VERSION_MIN_REQUIRED +#endif + +void ff_metal_compute_encoder_dispatch(id device, + id pipeline, + id encoder, + NSUInteger width, NSUInteger height) + API_AVAILABLE(macos(10.11), ios(8.0)); + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *avclass, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format) + API_AVAILABLE(macos(10.11), ios(8.0)); + +#endif /* AVFILTER_METAL_UTILS_H */ diff --git a/libavfilter/metal/utils.m b/libavfilter/metal/utils.m new file mode 100644 index 0000000000..f365d3ceea --- /dev/null +++ b/libavfilter/metal/utils.m @@ -0,0 +1,76 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/log.h" +#include "utils.h" + +void ff_metal_compute_encoder_dispatch(id device, + id pipeline, + id encoder, + NSUInteger width, NSUInteger height) +{ + [encoder setComputePipelineState:pipeline]; + NSUInteger w = pipeline.threadExecutionWidth; + NSUInteger h = pipeline.maxTotalThreadsPerThreadgroup / w; + MTLSize threadsPerThreadgroup = MTLSizeMake(w, h, 1); + BOOL fallback = YES; + // MAC_OS_X_VERSION_10_15 is only defined on SDKs new enough to include its functionality (including iOS, tvOS, etc) +#ifdef MAC_OS_X_VERSION_10_15 + if (@available(macOS 10.15, iOS 11, tvOS 14.5, *)) { + if ([device supportsFamily:MTLGPUFamilyCommon3]) { + MTLSize threadsPerGrid = MTLSizeMake(width, height, 1); + [encoder dispatchThreads:threadsPerGrid threadsPerThreadgroup:threadsPerThreadgroup]; + fallback = NO; + } + } +#endif + if (fallback) { + MTLSize threadgroups = MTLSizeMake((width + w - 1) / w, + (height + h - 1) / h, + 1); + [encoder dispatchThreadgroups:threadgroups threadsPerThreadgroup:threadsPerThreadgroup]; + } +} + +CVMetalTextureRef ff_metal_texture_from_pixbuf(void *ctx, + CVMetalTextureCacheRef textureCache, + CVPixelBufferRef pixbuf, + int plane, + MTLPixelFormat format) +{ + CVMetalTextureRef tex = NULL; + CVReturn ret; + + ret = CVMetalTextureCacheCreateTextureFromImage( + NULL, + textureCache, + pixbuf, + NULL, + format, + CVPixelBufferGetWidthOfPlane(pixbuf, plane), + CVPixelBufferGetHeightOfPlane(pixbuf, plane), + plane, + &tex + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTexture from image: %d\n", ret); + return NULL; + } + + return tex; +} diff --git a/libavfilter/metal/vf_yadif_videotoolbox.metal b/libavfilter/metal/vf_yadif_videotoolbox.metal new file mode 100644 index 0000000000..8a3d41a30f --- /dev/null +++ b/libavfilter/metal/vf_yadif_videotoolbox.metal @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2018 Philip Langdale + * 2020 Aman Karmani + * 2020 Stefan Dyulgerov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 + +using namespace metal; + +/* + * Version compat shims + */ + +#if __METAL_VERSION__ < 210 +#define max3(x, y, z) max(x, max(y, z)) +#define min3(x, y, z) min(x, min(y, z)) +#endif + +/* + * Parameters + */ + +struct deintParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +/* + * Texture access helpers + */ + +#define accesstype access::sample +constexpr sampler s(coord::pixel); + +template +T tex2D(texture2d tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).x; +} + +template <> +float2 tex2D(texture2d tex, uint x, uint y) +{ + return tex.sample(s, float2(x, y)).xy; +} + +template +T tex2D(texture2d tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).x; +} + +template <> +float2 tex2D(texture2d tex, uint x, uint y) +{ + return tex.read(uint2(x, y)).xy; +} + +/* + * YADIF helpers + */ + +template +T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + T spatial_pred = (d + k)/2; + T spatial_score = abs(c - j) + abs(d - k) + abs(e - l); + + T score = abs(b - k) + abs(c - l) + abs(d - m); + if (score < spatial_score) { + spatial_pred = (c + l)/2; + spatial_score = score; + score = abs(a - l) + abs(b - m) + abs(c - n); + if (score < spatial_score) { + spatial_pred = (b + m)/2; + spatial_score = score; + } + } + score = abs(d - i) + abs(e - j) + abs(f - k); + if (score < spatial_score) { + spatial_pred = (e + j)/2; + spatial_score = score; + score = abs(e - h) + abs(f - i) + abs(g - j); + if (score < spatial_score) { + spatial_pred = (f + i)/2; + spatial_score = score; + } + } + return spatial_pred; +} + +template +T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + T p0 = (C + H) / 2; + T p1 = F; + T p2 = (D + I) / 2; + T p3 = G; + T p4 = (E + J) / 2; + + T tdiff0 = abs(D - I); + T tdiff1 = (abs(A - F) + abs(B - G)) / 2; + T tdiff2 = (abs(K - F) + abs(G - L)) / 2; + + T diff = max3(tdiff0, tdiff1, tdiff2); + + if (!skip_check) { + T maxi = max3(p2 - p3, p2 - p1, min(p0 - p1, p4 - p3)); + T mini = min3(p2 - p3, p2 - p1, max(p0 - p1, p4 - p3)); + diff = max3(diff, mini, -maxi); + } + + return clamp(spatial_pred, p2 - diff, p2 + diff); +} + +#define T float2 +template <> +T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + return T( + spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, + h.x, i.x, j.x, k.x, l.x, m.x, n.x), + spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, + h.y, i.y, j.y, k.y, l.y, m.y, n.y) + ); +} + +template <> +T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + return T( + temporal_predictor(A.x, B.x, C.x, D.x, E.x, F.x, + G.x, H.x, I.x, J.x, K.x, L.x, + spatial_pred.x, skip_check), + temporal_predictor(A.y, B.y, C.y, D.y, E.y, F.y, + G.y, H.y, I.y, J.y, K.y, L.y, + spatial_pred.y, skip_check) + ); +} +#undef T + +/* + * YADIF compute + */ + +template +T yadif_compute_spatial( + texture2d cur, + uint2 pos) +{ + // Calculate spatial prediction + T a = tex2D(cur, pos.x - 3, pos.y - 1); + T b = tex2D(cur, pos.x - 2, pos.y - 1); + T c = tex2D(cur, pos.x - 1, pos.y - 1); + T d = tex2D(cur, pos.x - 0, pos.y - 1); + T e = tex2D(cur, pos.x + 1, pos.y - 1); + T f = tex2D(cur, pos.x + 2, pos.y - 1); + T g = tex2D(cur, pos.x + 3, pos.y - 1); + + T h = tex2D(cur, pos.x - 3, pos.y + 1); + T i = tex2D(cur, pos.x - 2, pos.y + 1); + T j = tex2D(cur, pos.x - 1, pos.y + 1); + T k = tex2D(cur, pos.x - 0, pos.y + 1); + T l = tex2D(cur, pos.x + 1, pos.y + 1); + T m = tex2D(cur, pos.x + 2, pos.y + 1); + T n = tex2D(cur, pos.x + 3, pos.y + 1); + + return spatial_predictor(a, b, c, d, e, f, g, + h, i, j, k, l, m, n); +} + +template +T yadif_compute_temporal( + texture2d cur, + texture2d prev2, + texture2d prev1, + texture2d next1, + texture2d next2, + T spatial_pred, + bool skip_spatial_check, + uint2 pos) +{ + // Calculate temporal prediction + T A = tex2D(prev2, pos.x, pos.y - 1); + T B = tex2D(prev2, pos.x, pos.y + 1); + T C = tex2D(prev1, pos.x, pos.y - 2); + T D = tex2D(prev1, pos.x, pos.y + 0); + T E = tex2D(prev1, pos.x, pos.y + 2); + T F = tex2D(cur, pos.x, pos.y - 1); + T G = tex2D(cur, pos.x, pos.y + 1); + T H = tex2D(next1, pos.x, pos.y - 2); + T I = tex2D(next1, pos.x, pos.y + 0); + T J = tex2D(next1, pos.x, pos.y + 2); + T K = tex2D(next2, pos.x, pos.y - 1); + T L = tex2D(next2, pos.x, pos.y + 1); + + return temporal_predictor(A, B, C, D, E, F, G, H, I, J, K, L, + spatial_pred, skip_spatial_check); +} + +template +T yadif( + texture2d dst, + texture2d prev, + texture2d cur, + texture2d next, + constant deintParams& params, + uint2 pos) +{ + T spatial_pred = yadif_compute_spatial(cur, pos); + + if (params.is_second_field) { + return yadif_compute_temporal(cur, prev, cur, next, next, spatial_pred, params.skip_spatial_check, pos); + } else { + return yadif_compute_temporal(cur, prev, prev, cur, next, spatial_pred, params.skip_spatial_check, pos); + } +} + +/* + * Kernel dispatch + */ + +kernel void deint( + texture2d dst [[texture(0)]], + texture2d prev [[texture(1)]], + texture2d cur [[texture(2)]], + texture2d next [[texture(3)]], + constant deintParams& params [[buffer(4)]], + uint2 pos [[thread_position_in_grid]]) +{ + if ((pos.x >= dst.get_width()) || + (pos.y >= dst.get_height())) { + return; + } + + // Don't modify the primary field + if (pos.y % 2 == params.parity) { + float4 in = cur.read(pos); + dst.write(in, pos); + return; + } + + float2 pred; + if (params.channels == 1) + pred = float2(yadif(dst, prev, cur, next, params, pos)); + else + pred = yadif(dst, prev, cur, next, params, pos); + dst.write(pred.xyyy, pos); +} diff --git a/libavfilter/setpts.c b/libavfilter/setpts.c index fad92033e4..054feb05f1 100644 --- a/libavfilter/setpts.c +++ b/libavfilter/setpts.c @@ -294,6 +294,7 @@ const AVFilter ff_vf_setpts = { .init = init, .activate = activate, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, .priv_size = sizeof(SetPTSContext), .priv_class = &setpts_class, @@ -334,6 +335,7 @@ const AVFilter ff_af_asetpts = { .uninit = uninit, .priv_size = sizeof(SetPTSContext), .priv_class = &asetpts_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(asetpts_inputs), FILTER_OUTPUTS(asetpts_outputs), }; diff --git a/libavfilter/settb.c b/libavfilter/settb.c index ae2cf9b888..67d310afbd 100644 --- a/libavfilter/settb.c +++ b/libavfilter/settb.c @@ -185,6 +185,7 @@ const AVFilter ff_vf_settb = { FILTER_INPUTS(avfilter_vf_settb_inputs), FILTER_OUTPUTS(avfilter_vf_settb_outputs), .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_SETTB_FILTER */ @@ -216,5 +217,6 @@ const AVFilter ff_af_asettb = { FILTER_OUTPUTS(avfilter_af_asettb_outputs), .priv_class = &asettb_class, .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_ASETTB_FILTER */ diff --git a/libavfilter/split.c b/libavfilter/split.c index a08ddf72b1..6b9b656708 100644 --- a/libavfilter/split.c +++ b/libavfilter/split.c @@ -112,7 +112,7 @@ const AVFilter ff_vf_split = { .init = split_init, FILTER_INPUTS(avfilter_vf_split_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; static const AVFilterPad avfilter_af_asplit_inputs[] = { @@ -131,5 +131,5 @@ const AVFilter ff_af_asplit = { .init = split_init, FILTER_INPUTS(avfilter_af_asplit_inputs), .outputs = NULL, - .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS, + .flags = AVFILTER_FLAG_DYNAMIC_OUTPUTS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c index 573f363705..b89a680883 100644 --- a/libavfilter/src_movie.c +++ b/libavfilter/src_movie.c @@ -67,12 +67,14 @@ typedef struct MovieContext { int loop_count; int64_t discontinuity_threshold; int64_t ts_offset; + int dec_threads; AVFormatContext *format_ctx; int max_stream_index; /**< max stream # actually used for output */ MovieStream *st; /**< array of all streams, one per output */ int *out_index; /**< stream number -> output number map, or -1 */ + AVDictionary *format_opts; } MovieContext; #define OFFSET(x) offsetof(MovieContext, x) @@ -90,6 +92,8 @@ static const AVOption movie_options[]= { { "s", "set streams", OFFSET(stream_specs), AV_OPT_TYPE_STRING, {.str = 0}, 0, 0, FLAGS }, { "loop", "set loop count", OFFSET(loop_count), AV_OPT_TYPE_INT, {.i64 = 1}, 0, INT_MAX, FLAGS }, { "discontinuity", "set discontinuity threshold", OFFSET(discontinuity_threshold), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, FLAGS }, + { "dec_threads", "set the number of threads for decoding", OFFSET(dec_threads), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS }, + { "format_opts", "set format options for the opened file", OFFSET(format_opts), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, FLAGS}, { NULL }, }; @@ -150,7 +154,7 @@ static AVStream *find_stream(void *log, AVFormatContext *avf, const char *spec) return found; } -static int open_stream(AVFilterContext *ctx, MovieStream *st) +static int open_stream(AVFilterContext *ctx, MovieStream *st, int dec_threads) { const AVCodec *codec; int ret; @@ -169,7 +173,9 @@ static int open_stream(AVFilterContext *ctx, MovieStream *st) if (ret < 0) return ret; - st->codec_ctx->thread_count = ff_filter_get_nb_threads(ctx); + if (!dec_threads) + dec_threads = ff_filter_get_nb_threads(ctx); + st->codec_ctx->thread_count = dec_threads; if ((ret = avcodec_open2(st->codec_ctx, codec, NULL)) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to open codec\n"); @@ -239,7 +245,7 @@ static av_cold int movie_common_init(AVFilterContext *ctx) iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL; movie->format_ctx = NULL; - if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) { + if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, &movie->format_opts)) < 0) { av_log(ctx, AV_LOG_ERROR, "Failed to avformat_open_input '%s'\n", movie->file_name); return ret; @@ -314,7 +320,7 @@ static av_cold int movie_common_init(AVFilterContext *ctx) if (ret < 0) return ret; } - ret = open_stream(ctx, &movie->st[i]); + ret = open_stream(ctx, &movie->st[i], movie->dec_threads); if (ret < 0) return ret; } diff --git a/libavfilter/tests/.gitignore b/libavfilter/tests/.gitignore index 65ef86f2e5..db482cd49b 100644 --- a/libavfilter/tests/.gitignore +++ b/libavfilter/tests/.gitignore @@ -1,3 +1,11 @@ +/dnn-layer-conv2d +/dnn-layer-depth2space +/dnn-layer-maximum +/dnn-layer-pad +/dnn-layer-mathbinary +/dnn-layer-mathunary +/dnn-layer-avgpool +/dnn-layer-dense /drawutils /filtfmts /formats diff --git a/tests/dnn/dnn-layer-avgpool-test.c b/libavfilter/tests/dnn-layer-avgpool.c similarity index 100% rename from tests/dnn/dnn-layer-avgpool-test.c rename to libavfilter/tests/dnn-layer-avgpool.c diff --git a/tests/dnn/dnn-layer-conv2d-test.c b/libavfilter/tests/dnn-layer-conv2d.c similarity index 100% rename from tests/dnn/dnn-layer-conv2d-test.c rename to libavfilter/tests/dnn-layer-conv2d.c diff --git a/tests/dnn/dnn-layer-dense-test.c b/libavfilter/tests/dnn-layer-dense.c similarity index 100% rename from tests/dnn/dnn-layer-dense-test.c rename to libavfilter/tests/dnn-layer-dense.c diff --git a/tests/dnn/dnn-layer-depth2space-test.c b/libavfilter/tests/dnn-layer-depth2space.c similarity index 100% rename from tests/dnn/dnn-layer-depth2space-test.c rename to libavfilter/tests/dnn-layer-depth2space.c diff --git a/tests/dnn/dnn-layer-mathbinary-test.c b/libavfilter/tests/dnn-layer-mathbinary.c similarity index 100% rename from tests/dnn/dnn-layer-mathbinary-test.c rename to libavfilter/tests/dnn-layer-mathbinary.c diff --git a/tests/dnn/dnn-layer-mathunary-test.c b/libavfilter/tests/dnn-layer-mathunary.c similarity index 100% rename from tests/dnn/dnn-layer-mathunary-test.c rename to libavfilter/tests/dnn-layer-mathunary.c diff --git a/tests/dnn/dnn-layer-maximum-test.c b/libavfilter/tests/dnn-layer-maximum.c similarity index 100% rename from tests/dnn/dnn-layer-maximum-test.c rename to libavfilter/tests/dnn-layer-maximum.c diff --git a/tests/dnn/dnn-layer-pad-test.c b/libavfilter/tests/dnn-layer-pad.c similarity index 100% rename from tests/dnn/dnn-layer-pad-test.c rename to libavfilter/tests/dnn-layer-pad.c diff --git a/libavfilter/trim.c b/libavfilter/trim.c index c260da3a0b..e627903c64 100644 --- a/libavfilter/trim.c +++ b/libavfilter/trim.c @@ -363,6 +363,7 @@ const AVFilter ff_af_atrim = { .init = init, .priv_size = sizeof(TrimContext), .priv_class = &atrim_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(atrim_inputs), FILTER_OUTPUTS(atrim_outputs), }; diff --git a/libavfilter/v360.h b/libavfilter/v360.h index 05e3435b44..5d797ab828 100644 --- a/libavfilter/v360.h +++ b/libavfilter/v360.h @@ -142,6 +142,7 @@ typedef struct V360Context { int fin_pad, fout_pad; float yaw, pitch, roll; + float h_offset, v_offset; int ih_flip, iv_flip; int h_flip, v_flip, d_flip; diff --git a/libavfilter/version.h b/libavfilter/version.h index c04bb7da0d..1a9849ef82 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -30,7 +30,7 @@ #include "libavutil/version.h" #define LIBAVFILTER_VERSION_MAJOR 8 -#define LIBAVFILTER_VERSION_MINOR 15 +#define LIBAVFILTER_VERSION_MINOR 25 #define LIBAVFILTER_VERSION_MICRO 100 @@ -50,14 +50,8 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_SWS_PARAM_OPTION #define FF_API_SWS_PARAM_OPTION (LIBAVFILTER_VERSION_MAJOR < 9) -#endif -#ifndef FF_API_BUFFERSINK_ALLOC #define FF_API_BUFFERSINK_ALLOC (LIBAVFILTER_VERSION_MAJOR < 9) -#endif -#ifndef FF_API_PAD_COUNT #define FF_API_PAD_COUNT (LIBAVFILTER_VERSION_MAJOR < 9) -#endif #endif /* AVFILTER_VERSION_H */ diff --git a/libavfilter/vf_addroi.c b/libavfilter/vf_addroi.c index 5f9ec21754..dd3daeda81 100644 --- a/libavfilter/vf_addroi.c +++ b/libavfilter/vf_addroi.c @@ -262,6 +262,8 @@ const AVFilter ff_vf_addroi = { .priv_size = sizeof(AddROIContext), .priv_class = &addroi_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(addroi_inputs), FILTER_OUTPUTS(addroi_outputs), }; diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 995c7f4f14..2d1eaa954b 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -188,6 +188,7 @@ const AVFilter ff_vf_setdar = { .description = NULL_IF_CONFIG_SMALL("Set the frame display aspect ratio."), .priv_size = sizeof(AspectContext), .priv_class = &setdar_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_setdar_inputs), FILTER_OUTPUTS(avfilter_vf_setdar_outputs), }; @@ -250,6 +251,7 @@ const AVFilter ff_vf_setsar = { .description = NULL_IF_CONFIG_SMALL("Set the pixel sample aspect ratio."), .priv_size = sizeof(AspectContext), .priv_class = &setsar_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_setsar_inputs), FILTER_OUTPUTS(avfilter_vf_setsar_outputs), }; diff --git a/libavfilter/vf_avgblur_vulkan.c b/libavfilter/vf_avgblur_vulkan.c index 93a7f0d62a..d118ce802c 100644 --- a/libavfilter/vf_avgblur_vulkan.c +++ b/libavfilter/vf_avgblur_vulkan.c @@ -18,18 +18,19 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #define CGS 32 typedef struct AvgBlurVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl_hor; - VulkanPipeline *pl_ver; + FFVulkanPipeline *pl_hor; + FFVulkanPipeline *pl_ver; /* Shader updators, must be in the main filter struct */ VkDescriptorImageInfo input_images[3]; @@ -70,19 +71,18 @@ static const char blur_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - SPIRVShader *shd; + FFVkSPIRVShader *shd; AvgBlurVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_LINEAR); - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), }, { .name = "output_img", @@ -95,27 +95,28 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - if (!sampler) - return AVERROR_EXTERNAL; + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + desc_i[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!desc_i[0].sampler) + return AVERROR_EXTERNAL; { /* Create shader for the horizontal pass */ desc_i[0].updater = s->input_images; desc_i[1].updater = s->tmp_images; - s->pl_hor = ff_vk_create_pipeline(ctx); + s->pl_hor = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl_hor) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(ctx, s->pl_hor, "avgblur_compute_hor", + shd = ff_vk_init_shader(s->pl_hor, "avgblur_compute_hor", VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ CGS, 1, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_hor, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_hor, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_x - 1); GLSLC(0, #define INC(x) (ivec2(x, 0)) ); @@ -139,26 +140,28 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_hor)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_hor)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl_hor)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl_hor)); } { /* Create shader for the vertical pass */ desc_i[0].updater = s->tmp_images; desc_i[1].updater = s->output_images; - s->pl_ver = ff_vk_create_pipeline(ctx); + s->pl_ver = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl_ver) return AVERROR(ENOMEM); - shd = ff_vk_init_shader(ctx, s->pl_ver, "avgblur_compute_ver", + shd = ff_vk_init_shader(s->pl_ver, "avgblur_compute_ver", VK_SHADER_STAGE_COMPUTE_BIT); + if (!shd) + return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, (int [3]){ 1, CGS, 1 }); + ff_vk_set_compute_shader_sizes(shd, (int [3]){ 1, CGS, 1 }); - RET(ff_vk_add_descriptor_set(ctx, s->pl_ver, shd, desc_i, 2, 0)); + RET(ff_vk_add_descriptor_set(vkctx, s->pl_ver, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); GLSLF(0, #define FILTER_RADIUS (%i) ,s->size_y - 1); GLSLC(0, #define INC(x) (ivec2(0, x)) ); @@ -182,14 +185,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); - RET(ff_vk_init_pipeline_layout(ctx, s->pl_ver)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl_ver)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl_ver)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl_ver)); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -204,29 +207,35 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f int err; VkCommandBuffer cmd_buf; AvgBlurVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *tmp = (AVVkFrame *)tmp_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->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); + int planes = av_pix_fmt_count_planes(s->vkctx.output_format); /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + 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(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], + input_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->tmp_images[i].imageView, - tmp->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->tmp_images[i].imageView, tmp->img[i], + output_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], ff_comp_identity_map)); s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -234,8 +243,8 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl_hor, 0); - ff_vk_update_descriptor_set(avctx, s->pl_ver, 0); + ff_vk_update_descriptor_set(vkctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(vkctx, s->pl_ver, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[] = { @@ -280,9 +289,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + 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(bar), bar); in->layout[i] = bar[0].newLayout; in->access[i] = bar[0].dstAccessMask; @@ -294,27 +303,29 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *tmp_f out->access[i] = bar[2].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_hor); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_hor); - vkCmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, s->vkctx.output_height, 1); - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl_ver); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl_ver); - vkCmdDispatch(cmd_buf, s->vkctx.output_width, - FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); + vk->CmdDispatch(cmd_buf, s->vkctx.output_width, + FFALIGN(s->vkctx.output_height, CGS)/CGS, 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx,s->exec); if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -363,7 +374,7 @@ static void avgblur_vulkan_uninit(AVFilterContext *avctx) { AvgBlurVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vf_bbox.c b/libavfilter/vf_bbox.c index 559ca505bf..02893d500d 100644 --- a/libavfilter/vf_bbox.c +++ b/libavfilter/vf_bbox.c @@ -151,6 +151,6 @@ const AVFilter ff_vf_bbox = { FILTER_INPUTS(bbox_inputs), FILTER_OUTPUTS(bbox_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, .process_command = ff_filter_process_command, }; diff --git a/libavfilter/vf_bilateral.c b/libavfilter/vf_bilateral.c index 2a4a3df6cc..41dc38d6f2 100644 --- a/libavfilter/vf_bilateral.c +++ b/libavfilter/vf_bilateral.c @@ -36,6 +36,7 @@ typedef struct BilateralContext { float sigmaR; int planes; + int nb_threads; int nb_planes; int depth; int planewidth[4]; @@ -44,14 +45,14 @@ typedef struct BilateralContext { float alpha; float range_table[65536]; - float *img_out_f; - float *img_temp; - float *map_factor_a; - float *map_factor_b; - float *slice_factor_a; - float *slice_factor_b; - float *line_factor_a; - float *line_factor_b; + float *img_out_f[4]; + float *img_temp[4]; + float *map_factor_a[4]; + float *map_factor_b[4]; + float *slice_factor_a[4]; + float *slice_factor_b[4]; + float *line_factor_a[4]; + float *line_factor_b[4]; } BilateralContext; #define OFFSET(x) offsetof(BilateralContext, x) @@ -102,6 +103,10 @@ static int config_params(AVFilterContext *ctx) return 0; } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -109,7 +114,6 @@ static int config_input(AVFilterLink *inlink) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); s->depth = desc->comp[0].depth; - config_params(ctx); s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w); @@ -118,134 +122,169 @@ static int config_input(AVFilterLink *inlink) s->planeheight[0] = s->planeheight[3] = inlink->h; s->nb_planes = av_pix_fmt_count_planes(inlink->format); + s->nb_threads = ff_filter_get_nb_threads(ctx); - s->img_out_f = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->img_temp = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->map_factor_a = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->map_factor_b = av_calloc(inlink->w * inlink->h, sizeof(float)); - s->slice_factor_a = av_calloc(inlink->w, sizeof(float)); - s->slice_factor_b = av_calloc(inlink->w, sizeof(float)); - s->line_factor_a = av_calloc(inlink->w, sizeof(float)); - s->line_factor_b = av_calloc(inlink->w, sizeof(float)); + for (int p = 0; p < s->nb_planes; p++) { + const int w = s->planewidth[p]; + const int h = s->planeheight[p]; - if (!s->img_out_f || - !s->img_temp || - !s->map_factor_a || - !s->map_factor_b || - !s->slice_factor_a || - !s->slice_factor_a || - !s->line_factor_a || - !s->line_factor_a) - return AVERROR(ENOMEM); + s->img_out_f[p] = av_calloc(w * h, sizeof(float)); + s->img_temp[p] = av_calloc(w * h, sizeof(float)); + s->map_factor_a[p] = av_calloc(w * h, sizeof(float)); + s->map_factor_b[p] = av_calloc(w * h, sizeof(float)); + s->slice_factor_a[p] = av_calloc(w, sizeof(float)); + s->slice_factor_b[p] = av_calloc(w, sizeof(float)); + s->line_factor_a[p] = av_calloc(w, sizeof(float)); + s->line_factor_b[p] = av_calloc(w, sizeof(float)); + + if (!s->img_out_f[p] || + !s->img_temp[p] || + !s->map_factor_a[p] || + !s->map_factor_b[p] || + !s->slice_factor_a[p] || + !s->slice_factor_a[p] || + !s->line_factor_a[p] || + !s->line_factor_a[p]) + return AVERROR(ENOMEM); + } return 0; } -#define BILATERAL(type, name) \ -static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t *ddst, \ - float sigma_spatial, float sigma_range, \ - int width, int height, int src_linesize, int dst_linesize) \ -{ \ - type *dst = (type *)ddst; \ - const type *src = (const type *)ssrc; \ - float *img_out_f = s->img_out_f, *img_temp = s->img_temp; \ - float *map_factor_a = s->map_factor_a, *map_factor_b = s->map_factor_b; \ - float *slice_factor_a = s->slice_factor_a, *slice_factor_b = s->slice_factor_b; \ - float *line_factor_a = s->line_factor_a, *line_factor_b = s->line_factor_b; \ - const float *range_table = s->range_table; \ - const float alpha = s->alpha; \ - float ypr, ycr, *ycy, *ypy, *xcy, fp, fc; \ - const float inv_alpha_ = 1.f - alpha; \ - float *ycf, *ypf, *xcf, *in_factor; \ - const type *tcy, *tpy; \ - int h1; \ - \ - for (int y = 0; y < height; y++) { \ - float *temp_factor_x, *temp_x = &img_temp[y * width]; \ - const type *in_x = &src[y * src_linesize]; \ - const type *texture_x = &src[y * src_linesize]; \ - type tpr; \ - \ - *temp_x++ = ypr = *in_x++; \ - tpr = *texture_x++; \ - \ - temp_factor_x = &map_factor_a[y * width]; \ - *temp_factor_x++ = fp = 1; \ - \ - for (int x = 1; x < width; x++) { \ - float alpha_; \ - int range_dist; \ - type tcr = *texture_x++; \ - type dr = abs(tcr - tpr); \ - \ - range_dist = dr; \ - alpha_ = range_table[range_dist]; \ - *temp_x++ = ycr = inv_alpha_*(*in_x++) + alpha_*ypr; \ - tpr = tcr; \ - ypr = ycr; \ - *temp_factor_x++ = fc = inv_alpha_ + alpha_ * fp; \ - fp = fc; \ - } \ - --temp_x; *temp_x = 0.5f*((*temp_x) + (*--in_x)); \ - tpr = *--texture_x; \ - ypr = *in_x; \ - \ - --temp_factor_x; *temp_factor_x = 0.5f*((*temp_factor_x) + 1); \ - fp = 1; \ - \ - for (int x = width - 2; x >= 0; x--) { \ - type tcr = *--texture_x; \ - type dr = abs(tcr - tpr); \ - int range_dist = dr; \ - float alpha_ = range_table[range_dist]; \ - \ - ycr = inv_alpha_ * (*--in_x) + alpha_ * ypr; \ - --temp_x; *temp_x = 0.5f*((*temp_x) + ycr); \ - tpr = tcr; \ - ypr = ycr; \ - \ - fc = inv_alpha_ + alpha_*fp; \ - --temp_factor_x; \ - *temp_factor_x = 0.5f*((*temp_factor_x) + fc); \ - fp = fc; \ - } \ - } \ - memcpy(img_out_f, img_temp, sizeof(float) * width); \ - \ - in_factor = map_factor_a; \ - memcpy(map_factor_b, in_factor, sizeof(float) * width); \ - for (int y = 1; y < height; y++) { \ - tpy = &src[(y - 1) * src_linesize]; \ - tcy = &src[y * src_linesize]; \ - xcy = &img_temp[y * width]; \ - ypy = &img_out_f[(y - 1) * width]; \ - ycy = &img_out_f[y * width]; \ - \ - xcf = &in_factor[y * width]; \ - ypf = &map_factor_b[(y - 1) * width]; \ - ycf = &map_factor_b[y * width]; \ - for (int x = 0; x < width; x++) { \ - type dr = abs((*tcy++) - (*tpy++)); \ - int range_dist = dr; \ - float alpha_ = range_table[range_dist]; \ - \ - *ycy++ = inv_alpha_*(*xcy++) + alpha_*(*ypy++); \ - *ycf++ = inv_alpha_*(*xcf++) + alpha_*(*ypf++); \ - } \ - } \ - h1 = height - 1; \ - ycf = line_factor_a; \ - ypf = line_factor_b; \ - memcpy(ypf, &in_factor[h1 * width], sizeof(float) * width); \ - for (int x = 0; x < width; x++) \ - map_factor_b[h1 * width + x] = 0.5f*(map_factor_b[h1 * width + x] + ypf[x]); \ - \ - ycy = slice_factor_a; \ - ypy = slice_factor_b; \ - memcpy(ypy, &img_temp[h1 * width], sizeof(float) * width); \ - for (int x = 0, k = 0; x < width; x++) { \ - int idx = h1 * width + x; \ - img_out_f[idx] = 0.5f*(img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ +#define BILATERAL_H(type, name) \ +static void bilateralh_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[plane] / sizeof(type); \ + const type *src = (const type *)in->data[plane]; \ + float *img_temp = s->img_temp[plane]; \ + float *map_factor_a = s->map_factor_a[plane]; \ + const float *const range_table = s->range_table; \ + const float alpha = s->alpha; \ + float ypr, ycr, fp, fc; \ + const float inv_alpha_ = 1.f - alpha; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + float *temp_factor_x, *temp_x = &img_temp[y * width]; \ + const type *in_x = &src[y * src_linesize]; \ + const type *texture_x = &src[y * src_linesize]; \ + type tpr; \ + \ + *temp_x++ = ypr = *in_x++; \ + tpr = *texture_x++; \ + \ + temp_factor_x = &map_factor_a[y * width]; \ + *temp_factor_x++ = fp = 1; \ + \ + for (int x = 1; x < width; x++) { \ + float alpha_; \ + int range_dist; \ + type tcr = *texture_x++; \ + type dr = abs(tcr - tpr); \ + \ + range_dist = dr; \ + alpha_ = range_table[range_dist]; \ + *temp_x++ = ycr = inv_alpha_*(*in_x++) + alpha_*ypr; \ + tpr = tcr; \ + ypr = ycr; \ + *temp_factor_x++ = fc = inv_alpha_ + alpha_ * fp; \ + fp = fc; \ + } \ + --temp_x; *temp_x = ((*temp_x) + (*--in_x)); \ + tpr = *--texture_x; \ + ypr = *in_x; \ + \ + --temp_factor_x; *temp_factor_x = ((*temp_factor_x) + 1); \ + fp = 1; \ + \ + for (int x = width - 2; x >= 0; x--) { \ + type tcr = *--texture_x; \ + type dr = abs(tcr - tpr); \ + int range_dist = dr; \ + float alpha_ = range_table[range_dist]; \ + \ + ycr = inv_alpha_ * (*--in_x) + alpha_ * ypr; \ + --temp_x; *temp_x = ((*temp_x) + ycr); \ + tpr = tcr; \ + ypr = ycr; \ + \ + fc = inv_alpha_ + alpha_*fp; \ + --temp_factor_x; \ + *temp_factor_x = ((*temp_factor_x) + fc); \ + fp = fc; \ + } \ + } \ +} + +BILATERAL_H(uint8_t, byte) +BILATERAL_H(uint16_t, word) + +#define BILATERAL_V(type, name) \ +static void bilateralv_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (width * jobnr) / nb_jobs; \ + const int slice_end = (width * (jobnr+1)) / nb_jobs; \ + const int src_linesize = in->linesize[plane] / sizeof(type); \ + const type *src = (const type *)in->data[plane] + slice_start; \ + float *img_out_f = s->img_out_f[plane] + slice_start; \ + float *img_temp = s->img_temp[plane] + slice_start; \ + float *map_factor_a = s->map_factor_a[plane] + slice_start; \ + float *map_factor_b = s->map_factor_b[plane] + slice_start; \ + float *slice_factor_a = s->slice_factor_a[plane] + slice_start; \ + float *slice_factor_b = s->slice_factor_b[plane] + slice_start; \ + float *line_factor_a = s->line_factor_a[plane] + slice_start; \ + float *line_factor_b = s->line_factor_b[plane] + slice_start; \ + const float *const range_table = s->range_table; \ + const float alpha = s->alpha; \ + float *ycy, *ypy, *xcy; \ + const float inv_alpha_ = 1.f - alpha; \ + float *ycf, *ypf, *xcf, *in_factor; \ + const type *tcy, *tpy; \ + int h1; \ + \ + memcpy(img_out_f, img_temp, sizeof(float) * (slice_end - slice_start)); \ + \ + in_factor = map_factor_a; \ + memcpy(map_factor_b, in_factor, sizeof(float) * (slice_end - slice_start)); \ + for (int y = 1; y < height; y++) { \ + tpy = &src[(y - 1) * src_linesize]; \ + tcy = &src[y * src_linesize]; \ + xcy = &img_temp[y * width]; \ + ypy = &img_out_f[(y - 1) * width]; \ + ycy = &img_out_f[y * width]; \ + \ + xcf = &in_factor[y * width]; \ + ypf = &map_factor_b[(y - 1) * width]; \ + ycf = &map_factor_b[y * width]; \ + for (int x = 0; x < slice_end - slice_start; x++) { \ + type dr = abs((*tcy++) - (*tpy++)); \ + int range_dist = dr; \ + float alpha_ = range_table[range_dist]; \ + \ + *ycy++ = inv_alpha_*(*xcy++) + alpha_*(*ypy++); \ + *ycf++ = inv_alpha_*(*xcf++) + alpha_*(*ypf++); \ + } \ + } \ + h1 = height - 1; \ + ycf = line_factor_a; \ + ypf = line_factor_b; \ + memcpy(ypf, &in_factor[h1 * width], sizeof(float) * (slice_end - slice_start)); \ + for (int x = 0, k = 0; x < slice_end - slice_start; x++) \ + map_factor_b[h1 * width + x] = (map_factor_b[h1 * width + x] + ypf[k++]); \ + \ + ycy = slice_factor_a; \ + ypy = slice_factor_b; \ + memcpy(ypy, &img_temp[h1 * width], sizeof(float) * (slice_end - slice_start)); \ + for (int x = 0, k = 0; x < slice_end - slice_start; x++) { \ + int idx = h1 * width + x; \ + img_out_f[idx] = (img_out_f[idx] + ypy[k++]) / map_factor_b[h1 * width + x]; \ } \ \ for (int y = h1 - 1; y >= 0; y--) { \ @@ -263,18 +302,18 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * ycf_ = ycf; \ ypf_ = ypf; \ factor_ = &map_factor_b[y * width]; \ - for (int x = 0; x < width; x++) { \ + for (int x = 0; x < slice_end - slice_start; x++) { \ type dr = abs((*tcy++) - (*tpy++)); \ int range_dist = dr; \ float alpha_ = range_table[range_dist]; \ float ycc, fcc = inv_alpha_*(*xcf++) + alpha_*(*ypf_++); \ \ *ycf_++ = fcc; \ - *factor_ = 0.5f * (*factor_ + fcc); \ + *factor_ = (*factor_ + fcc); \ \ ycc = inv_alpha_*(*xcy++) + alpha_*(*ypy_++); \ *ycy_++ = ycc; \ - *out_ = 0.5f * (*out_ + ycc) / (*factor_); \ + *out_ = (*out_ + ycc) / (*factor_); \ out_++; \ factor_++; \ } \ @@ -282,48 +321,140 @@ static void bilateral_##name(BilateralContext *s, const uint8_t *ssrc, uint8_t * ypy = ycy; \ ypf = ycf; \ } \ - \ - for (int i = 0; i < height; i++) \ - for (int j = 0; j < width; j++) \ - dst[j + i * dst_linesize] = img_out_f[i * width + j]; \ } -BILATERAL(uint8_t, byte) -BILATERAL(uint16_t, word) +BILATERAL_V(uint8_t, byte) +BILATERAL_V(uint16_t, word) + +#define BILATERAL_O(type, name) \ +static void bilateralo_##name(BilateralContext *s, AVFrame *out, AVFrame *in, \ + int jobnr, int nb_jobs, int plane) \ +{ \ + const int width = s->planewidth[plane]; \ + const int height = s->planeheight[plane]; \ + const int slice_start = (height * jobnr) / nb_jobs; \ + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ + const int dst_linesize = out->linesize[plane] / sizeof(type); \ + \ + for (int i = slice_start; i < slice_end; i++) { \ + type *dst = (type *)out->data[plane] + i * dst_linesize; \ + const float *const img_out_f = s->img_out_f[plane] + i * width; \ + for (int j = 0; j < width; j++) \ + dst[j] = lrintf(img_out_f[j]); \ + } \ +} + +BILATERAL_O(uint8_t, byte) +BILATERAL_O(uint16_t, word) + +static int bilateralh_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) + continue; + + if (s->depth <= 8) + bilateralh_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralh_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} + +static int bilateralv_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) + continue; + + if (s->depth <= 8) + bilateralv_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralv_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} + +static int bilateralo_planes(AVFilterContext *ctx, void *arg, + int jobnr, int nb_jobs) +{ + BilateralContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *out = td->out; + AVFrame *in = td->in; + + for (int plane = 0; plane < s->nb_planes; plane++) { + if (!(s->planes & (1 << plane))) { + if (out != in) { + const int height = s->planeheight[plane]; + const int slice_start = (height * jobnr) / nb_jobs; + const int slice_end = (height * (jobnr+1)) / nb_jobs; + const int width = s->planewidth[plane]; + const int linesize = in->linesize[plane]; + const int dst_linesize = out->linesize[plane]; + const uint8_t *src = in->data[plane]; + uint8_t *dst = out->data[plane]; + + av_image_copy_plane(dst + slice_start * dst_linesize, + dst_linesize, + src + slice_start * linesize, + linesize, + width * ((s->depth + 7) / 8), + slice_end - slice_start); + } + continue; + } + + if (s->depth <= 8) + bilateralo_byte(s, out, in, jobnr, nb_jobs, plane); + else + bilateralo_word(s, out, in, jobnr, nb_jobs, plane); + } + + return 0; +} static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; BilateralContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - 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); - - for (int plane = 0; plane < s->nb_planes; plane++) { - if (!(s->planes & (1 << plane))) { - av_image_copy_plane(out->data[plane], out->linesize[plane], - in->data[plane], in->linesize[plane], - s->planewidth[plane] * ((s->depth + 7) / 8), s->planeheight[plane]); - continue; + 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); } - - if (s->depth <= 8) - bilateral_byte(s, in->data[plane], out->data[plane], s->sigmaS, s->sigmaR, - s->planewidth[plane], s->planeheight[plane], - in->linesize[plane], out->linesize[plane]); - else - bilateral_word(s, in->data[plane], out->data[plane], s->sigmaS, s->sigmaR, - s->planewidth[plane], s->planeheight[plane], - in->linesize[plane] / 2, out->linesize[plane] / 2); + av_frame_copy_props(out, in); } - av_frame_free(&in); + td.in = in; + td.out = out; + ff_filter_execute(ctx, bilateralh_planes, &td, NULL, s->nb_threads); + ff_filter_execute(ctx, bilateralv_planes, &td, NULL, s->nb_threads); + ff_filter_execute(ctx, bilateralo_planes, &td, NULL, s->nb_threads); + + if (out != in) + av_frame_free(&in); return ff_filter_frame(outlink, out); } @@ -331,14 +462,16 @@ static av_cold void uninit(AVFilterContext *ctx) { BilateralContext *s = ctx->priv; - av_freep(&s->img_out_f); - av_freep(&s->img_temp); - av_freep(&s->map_factor_a); - av_freep(&s->map_factor_b); - av_freep(&s->slice_factor_a); - av_freep(&s->slice_factor_b); - av_freep(&s->line_factor_a); - av_freep(&s->line_factor_b); + for (int p = 0; p < s->nb_planes; p++) { + av_freep(&s->img_out_f[p]); + av_freep(&s->img_temp[p]); + av_freep(&s->map_factor_a[p]); + av_freep(&s->map_factor_b[p]); + av_freep(&s->slice_factor_a[p]); + av_freep(&s->slice_factor_b[p]); + av_freep(&s->line_factor_a[p]); + av_freep(&s->line_factor_b[p]); + } } static int process_command(AVFilterContext *ctx, @@ -381,6 +514,7 @@ const AVFilter ff_vf_bilateral = { FILTER_INPUTS(bilateral_inputs), FILTER_OUTPUTS(bilateral_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS, .process_command = process_command, }; diff --git a/libavfilter/vf_blackdetect.c b/libavfilter/vf_blackdetect.c index 93d5b077f1..99ff1ac606 100644 --- a/libavfilter/vf_blackdetect.c +++ b/libavfilter/vf_blackdetect.c @@ -257,5 +257,5 @@ const AVFilter ff_vf_blackdetect = { FILTER_PIXFMTS_ARRAY(pix_fmts), .uninit = uninit, .priv_class = &blackdetect_class, - .flags = AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index d37b3f3c13..e5e185dbea 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -127,6 +127,7 @@ const AVFilter ff_vf_blackframe = { .description = NULL_IF_CONFIG_SMALL("Detect frames that are (almost) black."), .priv_size = sizeof(BlackFrameContext), .priv_class = &blackframe_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_blackframe_inputs), FILTER_OUTPUTS(avfilter_vf_blackframe_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_blend.c b/libavfilter/vf_blend.c index b6f3c4fed3..2d433e439f 100644 --- a/libavfilter/vf_blend.c +++ b/libavfilter/vf_blend.c @@ -279,7 +279,11 @@ static AVFrame *blend_frame(AVFilterContext *ctx, AVFrame *top_buf, dst_buf = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!dst_buf) return top_buf; - av_frame_copy_props(dst_buf, top_buf); + + if (av_frame_copy_props(dst_buf, top_buf) < 0) { + av_frame_free(&dst_buf); + return top_buf; + } for (plane = 0; plane < s->nb_planes; plane++) { int hsub = plane == 1 || plane == 2 ? s->hsub : 0; diff --git a/libavfilter/vf_blend_vulkan.c b/libavfilter/vf_blend_vulkan.c new file mode 100644 index 0000000000..f3560332b5 --- /dev/null +++ b/libavfilter/vf_blend_vulkan.c @@ -0,0 +1,499 @@ +/* + * copyright (c) 2021 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_BLEND_MODE(NORMAL, A * opacity + B * (1.0f - opacity)) + +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) + 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" }, + + { "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_chromaber_vulkan.c b/libavfilter/vf_chromaber_vulkan.c index 9e0926c7c0..b9423e417e 100644 --- a/libavfilter/vf_chromaber_vulkan.c +++ b/libavfilter/vf_chromaber_vulkan.c @@ -18,17 +18,18 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #define CGROUPS (int [3]){ 32, 32, 1 } typedef struct ChromaticAberrationVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl; + FFVulkanPipeline *pl; /* Shader updators, must be in the main filter struct */ VkDescriptorImageInfo input_images[3]; @@ -67,18 +68,19 @@ static const char distort_chroma_kernel[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; + FFVkSampler *sampler; ChromaticAberrationVulkanContext *s = ctx->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); /* Create a sampler */ - VkSampler *sampler = ff_vk_init_sampler(ctx, 0, VK_FILTER_LINEAR); + sampler = ff_vk_init_sampler(vkctx, 0, VK_FILTER_LINEAR); if (!sampler) return AVERROR_EXTERNAL; - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; - - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); @@ -87,8 +89,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) s->opts.dist[1] = (s->opts.dist[1] / 100.0f) + 1.0f; { /* Create the shader */ - const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -96,7 +97,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->input_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -110,22 +111,22 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "chromaber_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "chromaber_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); GLSLC(0, layout(push_constant, std430) uniform pushConstants { ); GLSLC(1, vec2 dist; ); GLSLC(0, }; ); GLSLC(0, ); - ff_vk_add_push_constant(ctx, s->pl, 0, sizeof(s->opts), + ff_vk_add_push_constant(s->pl, 0, sizeof(s->opts), VK_SHADER_STAGE_COMPUTE_BIT); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ GLSLD( distort_chroma_kernel ); GLSLC(0, void main() ); @@ -152,14 +153,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) } GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -174,30 +175,34 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ChromaticAberrationVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *ouput_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + 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(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], + input_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + ouput_formats[i], ff_comp_identity_map)); s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[2] = { @@ -229,9 +234,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + 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(bar), bar); in->layout[i] = bar[0].newLayout; in->access[i] = bar[0].dstAccessMask; @@ -240,26 +245,28 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) out->access[i] = bar[1].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); - ff_vk_update_push_exec(avctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT, + ff_vk_update_push_exec(vkctx, s->exec, VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(s->opts), &s->opts); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -299,7 +306,7 @@ static void chromaber_vulkan_uninit(AVFilterContext *avctx) { ChromaticAberrationVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vf_chromanr.c b/libavfilter/vf_chromanr.c index 9c36e02c00..63ec8ff075 100644 --- a/libavfilter/vf_chromanr.c +++ b/libavfilter/vf_chromanr.c @@ -72,7 +72,8 @@ static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_NONE }; -#define SQR(x) ((x)*(x)) +#define MANHATTAN_DISTANCE(x, y, z) ((x) + (y) + (z)) +#define EUCLIDEAN_DISTANCE(x, y, z) (sqrtf((x)*(x) + (y)*(y) + (z)*(z))) #define FILTER_FUNC(distance, name, ctype, type, fun) \ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, \ @@ -136,19 +137,22 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, int sv = cv; \ int cn = 1; \ \ - for (int yy = FFMAX(0, y - sizeh); yy < FFMIN(y + sizeh, h); yy += steph) { \ + for (int yy = FFMAX(0, y - sizeh); yy <= FFMIN(y + sizeh, h - 1); yy += steph) { \ const type *in_yptr = (const type *)(in->data[0] + yy * chroma_h * in_ylinesize); \ const type *in_uptr = (const type *)(in->data[1] + yy * in_ulinesize); \ const type *in_vptr = (const type *)(in->data[2] + yy * in_vlinesize); \ \ - for (int xx = FFMAX(0, x - sizew); xx < FFMIN(x + sizew, w); xx += stepw) { \ + for (int xx = FFMAX(0, x - sizew); xx <= FFMIN(x + sizew, w - 1); xx += stepw) { \ const ctype Y = in_yptr[xx * chroma_w]; \ const ctype U = in_uptr[xx]; \ const ctype V = in_vptr[xx]; \ + const ctype cyY = FFABS(cy - Y); \ + const ctype cuU = FFABS(cu - U); \ + const ctype cvV = FFABS(cv - V); \ \ - if (fun(cu - U) + fun(cv - V) + fun(cy - Y) < thres && \ - fun(cu - U) < thres_u && fun(cv - V) < thres_v && \ - fun(cy - Y) < thres_y && \ + if (fun(cyY, cuU, cvV) < thres && \ + cuU < thres_u && cvV < thres_v && \ + cyY < thres_y && \ xx != x && yy != y) { \ su += U; \ sv += V; \ @@ -168,11 +172,11 @@ static int distance ## _slice##name(AVFilterContext *ctx, void *arg, return 0; \ } -FILTER_FUNC(manhattan, 8, int, uint8_t, FFABS) -FILTER_FUNC(manhattan, 16, int, uint16_t, FFABS) +FILTER_FUNC(manhattan, 8, int, uint8_t, MANHATTAN_DISTANCE) +FILTER_FUNC(manhattan, 16, int, uint16_t, MANHATTAN_DISTANCE) -FILTER_FUNC(euclidean, 8, int, uint8_t, SQR) -FILTER_FUNC(euclidean, 16, int64_t, uint16_t, SQR) +FILTER_FUNC(euclidean, 8, int, uint8_t, EUCLIDEAN_DISTANCE) +FILTER_FUNC(euclidean, 16, int64_t, uint16_t, EUCLIDEAN_DISTANCE) static int filter_frame(AVFilterLink *inlink, AVFrame *in) { @@ -238,14 +242,14 @@ static int config_input(AVFilterLink *inlink) #define VF AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM static const AVOption chromanr_options[] = { - { "thres", "set y+u+v threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=30}, 1, 5000, VF }, + { "thres", "set y+u+v threshold", OFFSET(threshold), AV_OPT_TYPE_FLOAT, {.dbl=30}, 1, 200, VF }, { "sizew", "set horizontal size", OFFSET(sizew), AV_OPT_TYPE_INT, {.i64=5}, 1, 100, VF }, { "sizeh", "set vertical size", OFFSET(sizeh), AV_OPT_TYPE_INT, {.i64=5}, 1, 100, VF }, { "stepw", "set horizontal step", OFFSET(stepw), AV_OPT_TYPE_INT, {.i64=1}, 1, 50, VF }, { "steph", "set vertical step", OFFSET(steph), AV_OPT_TYPE_INT, {.i64=1}, 1, 50, VF }, - { "threy", "set y threshold", OFFSET(threshold_y), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, - { "threu", "set u threshold", OFFSET(threshold_u), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, - { "threv", "set v threshold", OFFSET(threshold_v), AV_OPT_TYPE_FLOAT, {.dbl=5000},1, 5000, VF }, + { "threy", "set y threshold", OFFSET(threshold_y), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, + { "threu", "set u threshold", OFFSET(threshold_u), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, + { "threv", "set v threshold", OFFSET(threshold_v), AV_OPT_TYPE_FLOAT, {.dbl=200},1, 200, VF }, { "distance", "set distance type", OFFSET(distance), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, VF, "distance" }, { "manhattan", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, VF, "distance" }, { "euclidean", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, VF, "distance" }, diff --git a/libavfilter/vf_convolution.c b/libavfilter/vf_convolution.c index cc9ba2399e..6e6fe0d887 100644 --- a/libavfilter/vf_convolution.c +++ b/libavfilter/vf_convolution.c @@ -699,106 +699,24 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) return 0; } -static int config_input(AVFilterLink *inlink) +static int param_init(AVFilterContext *ctx) { - AVFilterContext *ctx = inlink->dst; ConvolutionContext *s = ctx->priv; + AVFilterLink *inlink = ctx->inputs[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int p; - - s->depth = desc->comp[0].depth; - s->max = (1 << s->depth) - 1; - - 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->nb_planes = av_pix_fmt_count_planes(inlink->format); - s->nb_threads = ff_filter_get_nb_threads(ctx); - s->bpc = (s->depth + 7) / 8; - - if (!strcmp(ctx->filter->name, "convolution")) { - if (s->depth > 8) { - for (p = 0; p < s->nb_planes; p++) { - if (s->mode[p] == MATRIX_ROW) - s->filter[p] = filter16_row; - else if (s->mode[p] == MATRIX_COLUMN) - s->filter[p] = filter16_column; - else if (s->size[p] == 3) - s->filter[p] = filter16_3x3; - else if (s->size[p] == 5) - s->filter[p] = filter16_5x5; - else if (s->size[p] == 7) - s->filter[p] = filter16_7x7; - } - } -#if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64 - ff_convolution_init_x86(s); -#endif - } else if (!strcmp(ctx->filter->name, "prewitt")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_prewitt; - } else if (!strcmp(ctx->filter->name, "roberts")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_roberts; - } else if (!strcmp(ctx->filter->name, "sobel")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_sobel; - } else if (!strcmp(ctx->filter->name, "kirsch")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_kirsch; - } else if (!strcmp(ctx->filter->name, "scharr")) { - if (s->depth > 8) - for (p = 0; p < s->nb_planes; p++) - s->filter[p] = filter16_scharr; - } - - return 0; -} - -static int filter_frame(AVFilterLink *inlink, AVFrame *in) -{ - AVFilterContext *ctx = inlink->dst; - ConvolutionContext *s = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - AVFrame *out; - ThreadData td; - - 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, filter_slice, &td, NULL, - FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads)); - - av_frame_free(&in); - return ff_filter_frame(outlink, out); -} - -static av_cold int init(AVFilterContext *ctx) -{ - ConvolutionContext *s = ctx->priv; - int i; + int p, i; if (!strcmp(ctx->filter->name, "convolution")) { for (i = 0; i < 4; i++) { int *matrix = (int *)s->matrix[i]; - char *p, *arg, *saveptr = NULL; - float sum = 0; + char *orig, *p, *arg, *saveptr = NULL; + float sum = 1.f; - p = s->matrix_str[i]; + p = orig = av_strdup(s->matrix_str[i]); if (p) { s->matrix_length[i] = 0; + s->rdiv[i] = 0.f; + sum = 0.f; while (s->matrix_length[i] < 49) { if (!(arg = av_strtok(p, " |", &saveptr))) @@ -810,6 +728,7 @@ static av_cold int init(AVFilterContext *ctx) s->matrix_length[i]++; } + av_freep(&orig); if (!(s->matrix_length[i] & 1)) { av_log(ctx, AV_LOG_ERROR, "number of matrix elements must be odd\n"); return AVERROR(EINVAL); @@ -866,10 +785,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "prewitt")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_prewitt; - else - s->copy[i] = 1; + s->filter[i] = filter_prewitt; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -877,10 +794,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "roberts")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_roberts; - else - s->copy[i] = 1; + s->filter[i] = filter_roberts; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -888,10 +803,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "sobel")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_sobel; - else - s->copy[i] = 1; + s->filter[i] = filter_sobel; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -899,10 +812,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "kirsch")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_kirsch; - else - s->copy[i] = 1; + s->filter[i] = filter_kirsch; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -910,10 +821,8 @@ static av_cold int init(AVFilterContext *ctx) } } else if (!strcmp(ctx->filter->name, "scharr")) { for (i = 0; i < 4; i++) { - if ((1 << i) & s->planes) - s->filter[i] = filter_scharr; - else - s->copy[i] = 1; + s->filter[i] = filter_scharr; + s->copy[i] = !((1 << i) & s->planes); s->size[i] = 3; s->setup[i] = setup_3x3; s->rdiv[i] = s->scale; @@ -921,9 +830,91 @@ static av_cold int init(AVFilterContext *ctx) } } + s->depth = desc->comp[0].depth; + s->max = (1 << s->depth) - 1; + + 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->nb_planes = av_pix_fmt_count_planes(inlink->format); + s->nb_threads = ff_filter_get_nb_threads(ctx); + s->bpc = (s->depth + 7) / 8; + + if (!strcmp(ctx->filter->name, "convolution")) { + if (s->depth > 8) { + for (p = 0; p < s->nb_planes; p++) { + if (s->mode[p] == MATRIX_ROW) + s->filter[p] = filter16_row; + else if (s->mode[p] == MATRIX_COLUMN) + s->filter[p] = filter16_column; + else if (s->size[p] == 3) + s->filter[p] = filter16_3x3; + else if (s->size[p] == 5) + s->filter[p] = filter16_5x5; + else if (s->size[p] == 7) + s->filter[p] = filter16_7x7; + } + } +#if CONFIG_CONVOLUTION_FILTER && ARCH_X86_64 + ff_convolution_init_x86(s); +#endif + } else if (!strcmp(ctx->filter->name, "prewitt")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_prewitt; + } else if (!strcmp(ctx->filter->name, "roberts")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_roberts; + } else if (!strcmp(ctx->filter->name, "sobel")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_sobel; + } else if (!strcmp(ctx->filter->name, "kirsch")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_kirsch; + } else if (!strcmp(ctx->filter->name, "scharr")) { + if (s->depth > 8) + for (p = 0; p < s->nb_planes; p++) + s->filter[p] = filter16_scharr; + } + return 0; } +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + return param_init(ctx); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + ConvolutionContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFrame *out; + ThreadData td; + + 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, filter_slice, &td, NULL, + FFMIN3(s->planeheight[1], s->planewidth[1], s->nb_threads)); + + av_frame_free(&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) { @@ -933,7 +924,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar if (ret < 0) return ret; - return init(ctx); + return param_init(ctx); } static const AVFilterPad convolution_inputs[] = { @@ -959,7 +950,6 @@ const AVFilter ff_vf_convolution = { .description = NULL_IF_CONFIG_SMALL("Apply convolution filter."), .priv_size = sizeof(ConvolutionContext), .priv_class = &convolution_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -986,7 +976,6 @@ const AVFilter ff_vf_prewitt = { .description = NULL_IF_CONFIG_SMALL("Apply prewitt operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1003,7 +992,6 @@ const AVFilter ff_vf_sobel = { .description = NULL_IF_CONFIG_SMALL("Apply sobel operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1020,7 +1008,6 @@ const AVFilter ff_vf_roberts = { .description = NULL_IF_CONFIG_SMALL("Apply roberts cross operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1037,7 +1024,6 @@ const AVFilter ff_vf_kirsch = { .description = NULL_IF_CONFIG_SMALL("Apply kirsch operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), @@ -1054,7 +1040,6 @@ const AVFilter ff_vf_scharr = { .description = NULL_IF_CONFIG_SMALL("Apply scharr operator."), .priv_size = sizeof(ConvolutionContext), .priv_class = &common_class, - .init = init, FILTER_INPUTS(convolution_inputs), FILTER_OUTPUTS(convolution_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c index 5554565bae..2fbced354f 100644 --- a/libavfilter/vf_copy.c +++ b/libavfilter/vf_copy.c @@ -75,6 +75,7 @@ static const AVFilterPad avfilter_vf_copy_outputs[] = { const AVFilter ff_vf_copy = { .name = "copy", .description = NULL_IF_CONFIG_SMALL("Copy the input video unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_copy_inputs), FILTER_OUTPUTS(avfilter_vf_copy_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index af3a8f333f..b887b9ecb1 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -273,5 +273,5 @@ const AVFilter ff_vf_cropdetect = { FILTER_INPUTS(avfilter_vf_cropdetect_inputs), FILTER_OUTPUTS(avfilter_vf_cropdetect_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_dblur.c b/libavfilter/vf_dblur.c index 8ea1229629..e821029906 100644 --- a/libavfilter/vf_dblur.c +++ b/libavfilter/vf_dblur.c @@ -68,7 +68,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) if (s->R3 > 0) { for (int y = 1; y < height - 1; y++) { - g = q * f(0, 0) + c * f(0, 0); + g = q * f(y, 0) + c * f(y, 0); for (int x = 0; x < width; x++) { f(y, x) = b0 * f(y, x) + b1 * f(y - 1, x) + g; g = q * f(y, x) + c * f(y - 1, x); @@ -84,7 +84,7 @@ static int filter_horizontally(AVFilterContext *ctx, int width, int height) } } else { for (int y = 1; y < height - 1; y++) { - g = q * f(0, width - 1) + c * f(0, width - 1); + g = q * f(y, width - 1) + c * f(y, width - 1); for (int x = width - 1; x >= 0; x--) { f(y, x) = b0 * f(y, x) + b1 * f(y - 1, x) + g; g = q * f(y, x) + c * f(y - 1, x); @@ -241,7 +241,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) if (s->depth == 8) { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst[x] = bptr[x]; + dst[x] = av_clip_uint8(lrintf(bptr[x])); } bptr += width; dst += out->linesize[plane]; @@ -249,7 +249,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } else { for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { - dst16[x] = bptr[x]; + dst16[x] = av_clip_uintp2_c(lrintf(bptr[x]), s->depth); } bptr += width; dst16 += out->linesize[plane] / 2; diff --git a/libavfilter/vf_deinterlace_vaapi.c b/libavfilter/vf_deinterlace_vaapi.c index 65f319ba9a..1304561034 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_entropy.c b/libavfilter/vf_entropy.c index 16569682a9..893d07d8e6 100644 --- a/libavfilter/vf_entropy.c +++ b/libavfilter/vf_entropy.c @@ -192,5 +192,5 @@ const AVFilter ff_vf_entropy = { FILTER_OUTPUTS(outputs), FILTER_PIXFMTS_ARRAY(pixfmts), .priv_class = &entropy_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_eq.c b/libavfilter/vf_eq.c index 4a0d85e8e5..80ab21efb3 100644 --- a/libavfilter/vf_eq.c +++ b/libavfilter/vf_eq.c @@ -236,9 +236,9 @@ static const enum AVPixelFormat pixel_fmts_eq[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P, - AV_PIX_FMT_YUV420P, - AV_PIX_FMT_YUV422P, - AV_PIX_FMT_YUV444P, + AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P, + AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P, + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P, AV_PIX_FMT_NONE }; @@ -281,12 +281,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) h = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); } - if (eq->param[i].adjust) - eq->param[i].adjust(&eq->param[i], out->data[i], out->linesize[i], - in->data[i], in->linesize[i], w, h); - else + if (i == 3 || !eq->param[i].adjust) av_image_copy_plane(out->data[i], out->linesize[i], in->data[i], in->linesize[i], w, h); + + else + eq->param[i].adjust(&eq->param[i], out->data[i], out->linesize[i], + in->data[i], in->linesize[i], w, h); } av_frame_free(&in); diff --git a/libavfilter/vf_estdif.c b/libavfilter/vf_estdif.c index a8ef93826c..0e5c9b4224 100644 --- a/libavfilter/vf_estdif.c +++ b/libavfilter/vf_estdif.c @@ -35,6 +35,9 @@ typedef struct ESTDIFContext { int deint; ///< which frames to deinterlace int rslope; ///< best edge slope search radius int redge; ///< best edge match search radius + float ecost; ///< edge cost for edge matching + float mcost; ///< middle cost for edge matching + float dcost; ///< distance cost for edge matching int interp; ///< type of interpolation int linesize[4]; ///< bytes of pixel data per line for each plane int planewidth[4]; ///< width of each plane @@ -42,7 +45,7 @@ typedef struct ESTDIFContext { int field; ///< which field are we on, 0 or 1 int eof; int depth; - int half; + int max; int nb_planes; int nb_threads; int64_t pts; @@ -52,7 +55,7 @@ typedef struct ESTDIFContext { const uint8_t *prev_line, const uint8_t *next_line, const uint8_t *prev2_line, const uint8_t *next2_line, const uint8_t *prev3_line, const uint8_t *next3_line, - int x, int width, int rslope, int redge, unsigned half, + int x, int width, int rslope, int redge, int depth, int *K); unsigned (*mid_8[3])(const uint8_t *const prev, @@ -92,6 +95,9 @@ 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, }, + { "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" }, CONST("2p", "two-point interpolation", 0, "interp"), CONST("4p", "four-point interpolation", 1, "interp"), @@ -215,10 +221,9 @@ MID6(uint16_t, 16) #define DIFF(type, ss) \ static unsigned diff_##ss(const type *const prev, \ const type *const next, \ - int end, int x, int k, int j) \ + int x, int y) \ { \ - return FFABS(prev[av_clip(x + k + j, 0, end)] - \ - next[av_clip(x - k + j, 0, end)]); \ + return FFABS(prev[x] - next[y]); \ } DIFF(uint8_t, 8) @@ -239,7 +244,7 @@ static unsigned cost_##ss(const type *const prev, \ COST(uint8_t, 8) COST(uint16_t, 16) -#define INTERPOLATE(type, atype, max, ss) \ +#define INTERPOLATE(type, atype, amax, ss) \ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const uint8_t *const pprev_line, \ const uint8_t *const nnext_line, \ @@ -248,7 +253,7 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const uint8_t *const pprev3_line, \ const uint8_t *const nnext3_line, \ int x, int width, int rslope, \ - int redge, unsigned h, int depth, \ + int redge, int depth, \ int *K) \ { \ type *dst = (type *)ddst; \ @@ -259,24 +264,28 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ const type *const next2_line = (const type *const)nnext2_line; \ const type *const next3_line = (const type *const)nnext3_line; \ const int interp = s->interp; \ + const int ecost = s->ecost * 32.f; \ + const int dcost = s->dcost * s->max; \ const int end = width - 1; \ - const atype f = redge + 2; \ + const atype mcost = s->mcost * s->redge * 4.f; \ atype sd[S], sD[S], di = 0; \ - atype dmin = max; \ + atype dmin = amax; \ int k = *K; \ \ for (int i = -rslope; i <= rslope && abs(k) > rslope; i++) { \ atype sum = 0; \ \ for (int j = -redge; j <= redge; j++) { \ - sum += diff_##ss(prev_line, next_line, end, x, i, j); \ - sum += diff_##ss(prev2_line, prev_line, end, x, i, j); \ - sum += diff_##ss(next_line, next2_line, end, x, i, j); \ + const int xx = av_clip(x + i + j, 0, end); \ + const int yy = av_clip(x - i + j, 0, end); \ + sum += diff_##ss(prev_line, next_line, xx, yy); \ + sum += diff_##ss(prev2_line, prev_line, xx, yy); \ + sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ - sD[i + rslope] = sum; \ - sD[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, i); \ - sD[i + rslope] += h * abs(i); \ + sD[i + rslope] = ecost * sum; \ + sD[i + rslope] += mcost * cost_##ss(prev_line, next_line, end, x, i);\ + sD[i + rslope] += dcost * abs(i); \ \ dmin = FFMIN(sD[i + rslope], dmin); \ } \ @@ -285,14 +294,16 @@ static void interpolate_##ss(ESTDIFContext *s, uint8_t *ddst, \ atype sum = 0; \ \ for (int j = -redge; j <= redge; j++) { \ - sum += diff_##ss(prev_line, next_line, end, x, k + i, j); \ - sum += diff_##ss(prev2_line, prev_line, end, x, k + i, j); \ - sum += diff_##ss(next_line, next2_line, end, x, k + i, j); \ + const int xx = av_clip(x + k + i + j, 0, end); \ + const int yy = av_clip(x - k - i + j, 0, end); \ + sum += diff_##ss(prev_line, next_line, xx, yy); \ + sum += diff_##ss(prev2_line, prev_line, xx, yy); \ + sum += diff_##ss(next_line, next2_line, xx, yy); \ } \ \ - sd[i + rslope] = sum; \ - sd[i + rslope] += f * cost_##ss(prev_line, next_line, end, x, k + i); \ - sd[i + rslope] += h * abs(k + i); \ + sd[i + rslope] = ecost * sum; \ + sd[i + rslope] += mcost * cost_##ss(prev_line, next_line, end, x, k+i);\ + sd[i + rslope] += dcost * abs(k + i); \ \ dmin = FFMIN(sd[i + rslope], dmin); \ } \ @@ -332,7 +343,6 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, AVFrame *in = td->in; const int rslope = s->rslope; const int redge = s->redge; - const int half = s->half; const int depth = s->depth; const int interlaced = in->interlaced_frame; const int tff = (s->field == (s->parity == -1 ? interlaced ? in->top_field_first : 1 : @@ -411,7 +421,7 @@ static int deinterlace_slice(AVFilterContext *ctx, void *arg, prev_line, next_line, prev2_line, next2_line, prev3_line, next3_line, - x, width, rslope, redge, half, depth, &k); + x, width, rslope, redge, depth, &k); } out_line += 2 * dst_linesize; @@ -475,7 +485,7 @@ static int config_input(AVFilterLink *inlink) s->mid_16[0] = mid2_16; s->mid_16[1] = mid4_16; s->mid_16[2] = mid6_16; - s->half = 1 << (s->depth - 1); + s->max = (1 << (s->depth)) - 1; return 0; } diff --git a/libavfilter/vf_find_rect.c b/libavfilter/vf_find_rect.c index 6ac714ce45..a536d669d1 100644 --- a/libavfilter/vf_find_rect.c +++ b/libavfilter/vf_find_rect.c @@ -294,6 +294,7 @@ const AVFilter ff_vf_find_rect = { .priv_size = sizeof(FOCContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(foc_inputs), FILTER_OUTPUTS(foc_outputs), FILTER_PIXFMTS(AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVJ420P), diff --git a/libavfilter/vf_flip_vulkan.c b/libavfilter/vf_flip_vulkan.c new file mode 100644 index 0000000000..0223786ef1 --- /dev/null +++ b/libavfilter/vf_flip_vulkan.c @@ -0,0 +1,369 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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" + +#define CGS 32 + +enum FlipType { + FLIP_VERTICAL, + FLIP_HORIZONTAL, + FLIP_BOTH +}; + +typedef struct FlipVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + + int initialized; +} FlipVulkanContext; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in, enum FlipType type) +{ + int err = 0; + FFVkSPIRVShader *shd; + FlipVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + 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, + .updater = s->input_images, + }, + { + .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, + .updater = s->output_images, + }, + }; + + image_descs[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(s->pl, "flip_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + 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)) { ); + switch (type) + { + case FLIP_HORIZONTAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.x - pos.x, pos.y)); ,i); + break; + case FLIP_VERTICAL: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(pos.x, size.y - pos.y)); ,i); + break; + case FLIP_BOTH: + GLSLF(2, vec4 res = texture(input_image[%i], ivec2(size.xy - pos.xy));, i); + break; + default: + GLSLF(2, vec4 res = texture(input_image[%i], pos); ,i); + break; + } + GLSLF(2, imageStore(output_image[%i], pos, res); ,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 av_cold void flip_vulkan_uninit(AVFilterContext *avctx) +{ + FlipVulkanContext *s = avctx->priv; + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) +{ + int err = 0; + VkCommandBuffer cmd_buf; + FlipVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &s->vkctx.vkfn; + AVVkFrame *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->data[0]; + const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); + 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(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->input_images[i].imageView, in->img[i], + input_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->input_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 = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->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); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + out->layout[i] = barriers[1].newLayout; + out->access[i] = barriers[1].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + s->vkctx.output_height, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, outframe, 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 filter_frame(AVFilterLink *link, AVFrame *in, enum FlipType type) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = link->dst; + FlipVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) + RET(init_filter(ctx, in, type)); + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static int hflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return filter_frame(link, in, FLIP_HORIZONTAL); +} + +static int vflip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return filter_frame(link, in, FLIP_VERTICAL); +} + +static int flip_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + return filter_frame(link, in, FLIP_BOTH); +} + +static const AVFilterPad flip_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + } +}; + +static const AVOption hflip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(hflip_vulkan); + +static const AVFilterPad hflip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &hflip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_hflip_vulkan = { + .name = "hflip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Horizontally flip the input video in Vulkan"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(hflip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &hflip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +static const AVOption vflip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(vflip_vulkan); + +static const AVFilterPad vflip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &vflip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_vflip_vulkan = { + .name = "vflip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Vertically flip the input video in Vulkan"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(vflip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &vflip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; + +static const AVOption flip_vulkan_options[] = { + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(flip_vulkan); + +static const AVFilterPad flip_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &flip_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +const AVFilter ff_vf_flip_vulkan = { + .name = "flip_vulkan", + .description = NULL_IF_CONFIG_SMALL("Flip both horizontally and vertically"), + .priv_size = sizeof(FlipVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &flip_vulkan_uninit, + FILTER_INPUTS(flip_vulkan_inputs), + FILTER_OUTPUTS(flip_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &flip_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index 7e15c43086..c78acbf87b 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -169,6 +169,8 @@ const AVFilter ff_vf_format = { .priv_size = sizeof(FormatContext), .priv_class = &format_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(avfilter_vf_format_inputs), FILTER_OUTPUTS(avfilter_vf_format_outputs), @@ -203,6 +205,8 @@ const AVFilter ff_vf_noformat = { .priv_size = sizeof(FormatContext), + .flags = AVFILTER_FLAG_METADATA_ONLY, + FILTER_INPUTS(avfilter_vf_noformat_inputs), FILTER_OUTPUTS(avfilter_vf_noformat_outputs), diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index b8714727fa..99e679441e 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -388,6 +388,7 @@ const AVFilter ff_vf_fps = { .priv_size = sizeof(FPSContext), .priv_class = &fps_class, .activate = activate, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_fps_inputs), FILTER_OUTPUTS(avfilter_vf_fps_outputs), }; diff --git a/libavfilter/vf_framestep.c b/libavfilter/vf_framestep.c index 5509df53e9..b8eee53b59 100644 --- a/libavfilter/vf_framestep.c +++ b/libavfilter/vf_framestep.c @@ -94,5 +94,5 @@ const AVFilter ff_vf_framestep = { .priv_class = &framestep_class, FILTER_INPUTS(framestep_inputs), FILTER_OUTPUTS(framestep_outputs), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_freezedetect.c b/libavfilter/vf_freezedetect.c index 99f0aae5a2..31a80a6dc0 100644 --- a/libavfilter/vf_freezedetect.c +++ b/libavfilter/vf_freezedetect.c @@ -217,6 +217,7 @@ const AVFilter ff_vf_freezedetect = { .priv_size = sizeof(FreezeDetectContext), .priv_class = &freezedetect_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(freezedetect_inputs), FILTER_OUTPUTS(freezedetect_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_gblur_vulkan.c b/libavfilter/vf_gblur_vulkan.c new file mode 100644 index 0000000000..a2e33d1c90 --- /dev/null +++ b/libavfilter/vf_gblur_vulkan.c @@ -0,0 +1,522 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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" + +#define CGS 32 +#define GBLUR_MAX_KERNEL_SIZE 127 + +typedef struct GBlurVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl_hor; + FFVulkanPipeline *pl_ver; + FFVkBuffer params_buf_hor; + FFVkBuffer params_buf_ver; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo tmp_images[3]; + VkDescriptorImageInfo output_images[3]; + VkDescriptorBufferInfo params_desc_hor; + VkDescriptorBufferInfo params_desc_ver; + + int initialized; + int size; + 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 inline float gaussian(float sigma, float x) +{ + return 1.0 / (sqrt(2.0 * M_PI) * sigma) * + exp(-(x * x) / (2.0 * sigma * sigma)); +} + +static inline float gaussian_simpson_integration(float sigma, float a, float b) +{ + return (b - a) * (1.0 / 6.0) * ((gaussian(sigma, a) + + 4.0 * gaussian(sigma, (a + b) * 0.5) + gaussian(sigma, b))); +} + +static void init_gaussian_kernel(float *kernel, float sigma, float kernel_size) +{ + int x; + float sum; + + sum = 0; + for (x = 0; x < kernel_size; x++) { + kernel[x] = gaussian_simpson_integration(sigma, x - 0.5f, x + 0.5f); + if (!x) + sum += kernel[x]; + else + sum += kernel[x] * 2.0; + } + /* Normalized */ + sum = 1.0 / sum; + for (x = 0; x < kernel_size; x++) { + kernel[x] *= sum; + } +} + +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; + s->tmpframe = NULL; +} + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + 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, + }, + }; + + FFVulkanDescriptorSetBinding buf_desc = { + .name = "data", + .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .mem_quali = "readonly", + .mem_layout = "std430", + .stages = VK_SHADER_STAGE_COMPUTE_BIT, + .updater = NULL, + .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); + if (!kernel_def) + return AVERROR(ENOMEM); + + buf_desc.buf_content = kernel_def; + + ff_vk_qf_init(&s->vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { /* 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) { + err = AVERROR(ENOMEM); + goto fail; + } + + shd = ff_vk_init_shader(s->pl_hor, "gblur_compute_hor", image_descs[0].stages); + if (!shd) { + err = AVERROR(ENOMEM); + goto fail; + } + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, CGS, 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); + } + + { /* 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) { + err = AVERROR(ENOMEM); + goto fail; + } + + shd = ff_vk_init_shader(s->pl_ver, "gblur_compute_ver", image_descs[0].stages); + if (!shd) { + err = AVERROR(ENOMEM); + goto fail; + } + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 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); + } + + RET(ff_vk_create_exec_ctx(&s->vkctx, &s->exec, &s->qf)); + + s->initialized = 1; + +fail: + av_free(kernel_def); + return err; +} + +static av_cold void gblur_vulkan_uninit(AVFilterContext *avctx) +{ + GBlurVulkanContext *s = avctx->priv; + + av_frame_free(&s->tmpframe); + + ff_vk_free_buf(&s->vkctx, &s->params_buf_hor); + ff_vk_free_buf(&s->vkctx, &s->params_buf_ver); + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *outframe, AVFrame *inframe) +{ + 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); + + 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], + input_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->tmp_images[i].imageView, + tmp->img[i], + output_formats[i], + ff_comp_identity_map)); + + RET(ff_vk_create_imageview(&s->vkctx, s->exec, &s->output_images[i].imageView, + out->img[i], + output_formats[i], + ff_comp_identity_map)); + + s->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + s->tmp_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; + } + + ff_vk_update_descriptor_set(&s->vkctx, s->pl_hor, 0); + ff_vk_update_descriptor_set(&s->vkctx, s->pl_ver, 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 = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->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 | VK_ACCESS_SHADER_READ_BIT, + .oldLayout = tmp->layout[i], + .newLayout = s->tmp_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = tmp->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); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + tmp->layout[i] = barriers[1].newLayout; + tmp->access[i] = barriers[1].dstAccessMask; + + out->layout[i] = barriers[2].newLayout; + out->access[i] = barriers[2].dstAccessMask; + } + + 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); + + ff_vk_bind_pipeline_exec(&s->vkctx, s->exec, s->pl_ver); + + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + 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); + ff_vk_add_exec_dep(&s->vkctx, s->exec, outframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + + err = ff_vk_submit_exec_queue(&s->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 gblur_vulkan_filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = link->dst; + GBlurVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) { + RET(init_filter(ctx, in)); + s->tmpframe = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!s->tmpframe) { + err = AVERROR(ENOMEM); + goto fail; + } + } + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + av_frame_free(&s->tmpframe); + + return err; +} + +#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 }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(gblur_vulkan); + +static const AVFilterPad gblur_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &gblur_vulkan_filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +static const AVFilterPad gblur_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &ff_vk_filter_config_output, + } +}; + +const AVFilter ff_vf_gblur_vulkan = { + .name = "gblur_vulkan", + .description = NULL_IF_CONFIG_SMALL("Gaussian Blur in Vulkan"), + .priv_size = sizeof(GBlurVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &gblur_vulkan_uninit, + FILTER_INPUTS(gblur_vulkan_inputs), + FILTER_OUTPUTS(gblur_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &gblur_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_histogram.c b/libavfilter/vf_histogram.c index fe13cb231b..bf80b2c4fc 100644 --- a/libavfilter/vf_histogram.c +++ b/libavfilter/vf_histogram.c @@ -85,8 +85,8 @@ static const AVOption histogram_options[] = { { "f", "set foreground opacity", OFFSET(fgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.7}, 0, 1, FLAGS}, { "bgopacity", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS}, { "b", "set background opacity", OFFSET(bgopacity), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS}, - { "colors_mode", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 6, FLAGS, "colors_mode"}, - { "l", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 6, FLAGS, "colors_mode"}, + { "colors_mode", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 9, FLAGS, "colors_mode"}, + { "l", "set colors mode", OFFSET(colors_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 9, FLAGS, "colors_mode"}, { "whiteonblack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "colors_mode" }, { "blackonwhite", NULL, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "colors_mode" }, { "whiteongray", NULL, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "colors_mode" }, @@ -94,6 +94,9 @@ static const AVOption histogram_options[] = { { "coloronblack", NULL, 0, AV_OPT_TYPE_CONST, {.i64=4}, 0, 0, FLAGS, "colors_mode" }, { "coloronwhite", NULL, 0, AV_OPT_TYPE_CONST, {.i64=5}, 0, 0, FLAGS, "colors_mode" }, { "colorongray" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=6}, 0, 0, FLAGS, "colors_mode" }, + { "blackoncolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=7}, 0, 0, FLAGS, "colors_mode" }, + { "whiteoncolor", NULL, 0, AV_OPT_TYPE_CONST, {.i64=8}, 0, 0, FLAGS, "colors_mode" }, + { "grayoncolor" , NULL, 0, AV_OPT_TYPE_CONST, {.i64=9}, 0, 0, FLAGS, "colors_mode" }, { NULL } }; @@ -312,6 +315,41 @@ static int config_input(AVFilterLink *inlink) memcpy(s->fg_color[1], blue_yuva_color, 4); memcpy(s->fg_color[2], red_yuva_color, 4); } + } else if (s->colors_mode == 7) { + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + FFSWAP(uint8_t, s->fg_color[i][j], s->bg_color[i][j]); + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], green_yuva_color, 4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } + } else if (s->colors_mode == 8) { + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], igreen_yuva_color,4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } + } else if (s->colors_mode == 9) { + for (int i = 0; i < 4; i++) + memcpy(s->fg_color[i], gray_color, 4); + if (rgb) { + memcpy(s->bg_color[0], red_gbrp_color, 4); + memcpy(s->bg_color[1], green_gbrp_color, 4); + memcpy(s->bg_color[2], blue_gbrp_color, 4); + } else { + memcpy(s->bg_color[0], igreen_yuva_color,4); + memcpy(s->bg_color[1], blue_yuva_color, 4); + memcpy(s->bg_color[2], red_yuva_color, 4); + } } } @@ -517,6 +555,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out->data[p][(j + starty) * out->linesize[p] + startx + i] = 255; } } + if (s->display_mode) { + for (j = col_height - 1; j >= 0; j--) { + for (l = 0; l < s->dncomp; l++) + out->data[l][(j + starty) * out->linesize[l] + startx + i] = s->bg_color[p][l]; + } + } for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) for (l = 0; l < s->dncomp; l++) out->data[l][(j + starty) * out->linesize[l] + startx + i] = p == l ? i : mid; @@ -531,6 +575,12 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AV_WN16(out->data[p] + (j + starty) * out->linesize[p] + startx * 2 + i * 2, 255 * mult); } } + if (s->display_mode) { + for (j = col_height - 1; j >= 0; j--) { + for (l = 0; l < s->dncomp; l++) + AV_WN16(out->data[l] + (j + starty) * out->linesize[l] + startx * 2 + i * 2, s->bg_color[p][l] * mult); + } + } for (j = s->level_height + s->scale_height - 1; j >= s->level_height; j--) for (l = 0; l < s->dncomp; l++) AV_WN16(out->data[l] + (j + starty) * out->linesize[l] + startx * 2 + i * 2, p == l ? i : mid * mult); diff --git a/libavfilter/vf_huesaturation.c b/libavfilter/vf_huesaturation.c new file mode 100644 index 0000000000..d4e3fea1c5 --- /dev/null +++ b/libavfilter/vf_huesaturation.c @@ -0,0 +1,479 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/opt.h" +#include "libavutil/imgutils.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#define R 0 +#define G 1 +#define B 2 + +#define REDS 0 +#define YELLOWS 1 +#define GREENS 2 +#define CYANS 3 +#define BLUES 4 +#define MAGENTAS 5 + +#define RED (1 << REDS) +#define YELLOW (1 << YELLOWS) +#define GREEN (1 << GREENS) +#define CYAN (1 << CYANS) +#define BLUE (1 << BLUES) +#define MAGENTA (1 << MAGENTAS) +#define ALL 0x3F + +typedef struct HueSaturationContext { + const AVClass *class; + + float hue; + float saturation; + float intensity; + float strength; + float rlw, glw, blw; + int lightness; + int colors; + + int depth; + int planewidth[4]; + int planeheight[4]; + + float matrix[4][4]; + int64_t imatrix[4][4]; + + int bpp; + int step; + uint8_t rgba_map[4]; + + int (*do_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); +} HueSaturationContext; + +#define DENOM 0x10000 + +static inline void get_triplet(int64_t m[4][4], int *r, int *g, int *b) +{ + const int ir = *r, ig = *g, ib = *b; + + *r = (ir * m[0][0] + ig * m[1][0] + ib * m[2][0] /*+ m[3][0]*/) >> 16; + *g = (ir * m[0][1] + ig * m[1][1] + ib * m[2][1] /*+ m[3][1]*/) >> 16; + *b = (ir * m[0][2] + ig * m[1][2] + ib * m[2][2] /*+ m[3][2]*/) >> 16; +} + +#define FAST_DIV255(x) ((((x) + 128) * 257) >> 16) + +static inline int lerpi8(int v0, int v1, int f, int max) +{ + return v0 + FAST_DIV255((v1 - v0) * f); +} + +static inline int lerpi16(int v0, int v1, int f, int max) +{ + return v0 + (v1 - v0) * (int64_t)f / max; +} + +#define HUESATURATION(name, type, clip, xall) \ +static int do_slice_##name##_##xall(AVFilterContext *ctx, \ + void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + HueSaturationContext *s = ctx->priv; \ + AVFrame *frame = arg; \ + const int imax = (1 << name) - 1; \ + const float strength = s->strength; \ + const int colors = s->colors; \ + const int step = s->step; \ + const int width = frame->width; \ + const int process_h = frame->height; \ + const int slice_start = (process_h * jobnr ) / nb_jobs; \ + const int slice_end = (process_h * (jobnr+1)) / nb_jobs; \ + const int linesize = frame->linesize[0] / sizeof(type); \ + type *row = (type *)frame->data[0] + 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]; \ + type *dst_r = row + offset_r; \ + type *dst_g = row + offset_g; \ + type *dst_b = row + offset_b; \ + \ + for (int y = slice_start; y < slice_end; y++) { \ + for (int x = 0; x < width * step; x += step) { \ + int ir, ig, ib, ro, go, bo; \ + \ + ir = ro = dst_r[x]; \ + ig = go = dst_g[x]; \ + ib = bo = dst_b[x]; \ + \ + if (xall) { \ + get_triplet(s->imatrix, &ir, &ig, &ib); \ + } else { \ + const int min = FFMIN3(ir, ig, ib); \ + const int max = FFMAX3(ir, ig, ib); \ + const int flags = (ir == max) << REDS \ + | (ir == min) << CYANS \ + | (ig == max) << GREENS \ + | (ig == min) << MAGENTAS \ + | (ib == max) << BLUES \ + | (ib == min) << YELLOWS; \ + if (colors & flags) { \ + int f = 0; \ + \ + if (colors & RED) \ + f = FFMAX(f, ir - FFMAX(ig, ib)); \ + if (colors & YELLOW) \ + f = FFMAX(f, FFMIN(ir, ig) - ib); \ + if (colors & GREEN) \ + f = FFMAX(f, ig - FFMAX(ir, ib)); \ + if (colors & CYAN) \ + f = FFMAX(f, FFMIN(ig, ib) - ir); \ + if (colors & BLUE) \ + f = FFMAX(f, ib - FFMAX(ir, ig)); \ + if (colors & MAGENTA) \ + f = FFMAX(f, FFMIN(ir, ib) - ig); \ + f = FFMIN(f * strength, imax); \ + get_triplet(s->imatrix, &ir, &ig, &ib); \ + ir = lerpi##name(ro, ir, f, imax); \ + ig = lerpi##name(go, ig, f, imax); \ + ib = lerpi##name(bo, ib, f, imax); \ + } \ + } \ + \ + dst_r[x] = clip(ir); \ + dst_g[x] = clip(ig); \ + dst_b[x] = clip(ib); \ + } \ + \ + dst_r += linesize; \ + dst_g += linesize; \ + dst_b += linesize; \ + } \ + \ + return 0; \ +} + +HUESATURATION(8, uint8_t, av_clip_uint8, 0) +HUESATURATION(16, uint16_t, av_clip_uint16, 0) + +HUESATURATION(8, uint8_t, av_clip_uint8, 1) +HUESATURATION(16, uint16_t, av_clip_uint16, 1) + +static void identity_matrix(float matrix[4][4]) +{ + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + matrix[y][x] = y == x; +} + +static void matrix_multiply(float a[4][4], float b[4][4], float c[4][4]) +{ + float temp[4][4]; + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + temp[y][x] = b[y][0] * a[0][x] + + b[y][1] * a[1][x] + + b[y][2] * a[2][x] + + b[y][3] * a[3][x]; + } + } + + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) + c[y][x] = temp[y][x]; + } +} + +static void colorscale_matrix(float matrix[4][4], float r, float g, float b) +{ + float temp[4][4]; + + temp[0][0] = r; temp[0][1] = 0.f; temp[0][2] = 0.f; temp[0][3] = 0.f; + temp[1][0] = 0.f; temp[1][1] = g; temp[1][2] = 0.f; temp[1][3] = 0.f; + temp[2][0] = 0.f; temp[2][1] = 0.f; temp[2][2] = b; temp[2][3] = 0.f; + temp[3][0] = 0.f; temp[3][1] = 0.f; temp[3][2] = 0.f; temp[3][3] = 1.f; + + matrix_multiply(temp, matrix, matrix); +} + +static void saturation_matrix(float matrix[4][4], float saturation, + float rlw, float glw, float blw) +{ + float s = 1.f - saturation; + float a = s * rlw + saturation; + float b = s * rlw; + float c = s * rlw; + float d = s * glw; + float e = s * glw + saturation; + float f = s * glw; + float g = s * blw; + float h = s * blw; + float i = s * blw + saturation; + float m[4][4]; + + m[0][0] = a; m[0][1] = b; m[0][2] = c; m[0][3] = 0.f; + m[1][0] = d; m[1][1] = e; m[1][2] = f; m[1][3] = 0.f; + m[2][0] = g; m[2][1] = h; m[2][2] = i; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void matrix2imatrix(float matrix[4][4], int64_t imatrix[4][4]) +{ + for (int y = 0; y < 4; y++) + for (int x = 0; x < 4; x++) + imatrix[y][x] = lrintf(matrix[y][x] * DENOM); +} + +static void x_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = 1.f; m[0][1] = 0.f; m[0][2] = 0.f; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = rc; m[1][2] = rs; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = -rs; m[2][2] = rc; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void y_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = rc; m[0][1] = 0.f; m[0][2] = -rs; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = 1.f; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = rs; m[2][1] = 0.f; m[2][2] = rc; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void z_rotate_matrix(float matrix[4][4], float rs, float rc) +{ + float m[4][4]; + + m[0][0] = rc; m[0][1] = rs; m[0][2] = 0.f; m[0][3] = 0.f; + m[1][0] = -rs; m[1][1] = rc; m[1][2] = 0.f; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = 1.f; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void z_shear_matrix(float matrix[4][4], float dx, float dy) +{ + float m[4][4]; + + m[0][0] = 1.f; m[0][1] = 0.f; m[0][2] = dx; m[0][3] = 0.f; + m[1][0] = 0.f; m[1][1] = 1.f; m[1][2] = dy; m[1][3] = 0.f; + m[2][0] = 0.f; m[2][1] = 0.f; m[2][2] = 1.f; m[2][3] = 0.f; + m[3][0] = 0.f; m[3][1] = 0.f; m[3][2] = 0.f; m[3][3] = 1.f; + + matrix_multiply(m, matrix, matrix); +} + +static void transform_point(float matrix[4][4], + float x, float y, float z, + float *tx, float *ty, float *tz) +{ + x = y; + *tx = x * matrix[0][0] + y * matrix[1][0] + z * matrix[2][0] + matrix[3][0]; + *ty = x * matrix[0][1] + y * matrix[1][1] + z * matrix[2][1] + matrix[3][1]; + *tz = x * matrix[0][2] + y * matrix[1][2] + z * matrix[2][2] + matrix[3][2]; +} + +static void hue_rotate_matrix(float matrix[4][4], float rotation, + float rlw, float glw, float blw) +{ + float mag, lx, ly, lz; + float xrs, xrc; + float yrs, yrc; + float zrs, zrc; + float zsx, zsy; + + mag = M_SQRT2; + xrs = 1.f / mag; + xrc = 1.f / mag; + x_rotate_matrix(matrix, xrs, xrc); + + mag = sqrtf(3.f); + yrs = -1.f / mag; + yrc = M_SQRT2 / mag; + y_rotate_matrix(matrix, yrs, yrc); + + transform_point(matrix, rlw, glw, blw, &lx, &ly, &lz); + zsx = lx / lz; + zsy = ly / lz; + z_shear_matrix(matrix, zsx, zsy); + + zrs = sinf(rotation * M_PI / 180.f); + zrc = cosf(rotation * M_PI / 180.f); + z_rotate_matrix(matrix, zrs, zrc); + + z_shear_matrix(matrix, -zsx, -zsy); + + y_rotate_matrix(matrix, -yrs, yrc); + x_rotate_matrix(matrix, -xrs, xrc); +} + +static void shue_rotate_matrix(float m[4][4], float rotation) +{ + float xrs, xrc, yrs, yrc, zrs, zrc, mag; + + mag = M_SQRT2; + xrs = 1.f / mag; + xrc = 1.f / mag; + x_rotate_matrix(m, xrs, xrc); + + mag = sqrtf(3.f); + yrs = -1.f / mag; + yrc = M_SQRT2 / mag; + y_rotate_matrix(m, yrs, yrc); + + zrs = sinf(rotation * M_PI / 180.f); + zrc = cosf(rotation * M_PI / 180.f); + z_rotate_matrix(m, zrs, zrc); + + y_rotate_matrix(m, -yrs, yrc); + x_rotate_matrix(m, -xrs, xrc); +} + +static void init_matrix(HueSaturationContext *s) +{ + float i = 1.f + s->intensity; + float saturation = 1.f + s->saturation; + float hue = s->hue; + + identity_matrix(s->matrix); + colorscale_matrix(s->matrix, i, i, i); + saturation_matrix(s->matrix, saturation, + s->rlw, s->glw, s->blw); + + if (s->lightness) + hue_rotate_matrix(s->matrix, hue, + s->rlw, s->glw, s->blw); + else + shue_rotate_matrix(s->matrix, hue); + + matrix2imatrix(s->matrix, s->imatrix); +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *frame) +{ + AVFilterContext *ctx = inlink->dst; + HueSaturationContext *s = ctx->priv; + + init_matrix(s); + + ff_filter_execute(ctx, s->do_slice[(s->strength >= 99.f) && (s->colors == ALL)], frame, NULL, + FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx))); + + return ff_filter_frame(ctx->outputs[0], frame); +} + +static const enum AVPixelFormat pixel_fmts[] = { + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_ARGB, + AV_PIX_FMT_0BGR, AV_PIX_FMT_0RGB, + AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0, + AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, + AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_NONE +}; + +static av_cold int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + HueSaturationContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + + s->depth = desc->comp[0].depth; + s->bpp = s->depth >> 3; + s->step = av_get_padded_bits_per_pixel(desc) >> (3 + (s->bpp == 2)); + ff_fill_rgba_map(s->rgba_map, inlink->format); + + 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->do_slice[0] = s->depth <= 8 ? do_slice_8_0 : do_slice_16_0; + s->do_slice[1] = s->depth <= 8 ? do_slice_8_1 : do_slice_16_1; + + return 0; +} + +static const AVFilterPad huesaturation_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .flags = AVFILTERPAD_FLAG_NEEDS_WRITABLE, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad huesaturation_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +#define OFFSET(x) offsetof(HueSaturationContext, x) +#define VF AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption huesaturation_options[] = { + { "hue", "set the hue shift", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl=0},-180, 180, VF }, + { "saturation", "set the saturation shift", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "intensity", "set the intensity shift", OFFSET(intensity), AV_OPT_TYPE_FLOAT, {.dbl=0}, -1, 1, VF }, + { "colors", "set colors range", OFFSET(colors), AV_OPT_TYPE_FLAGS, {.i64=ALL}, 0,ALL,VF, "colors" }, + { "r", "set reds", 0, AV_OPT_TYPE_CONST, {.i64=RED}, 0, 0, VF, "colors" }, + { "y", "set yellows", 0, AV_OPT_TYPE_CONST, {.i64=YELLOW}, 0, 0, VF, "colors" }, + { "g", "set greens", 0, AV_OPT_TYPE_CONST, {.i64=GREEN}, 0, 0, VF, "colors" }, + { "c", "set cyans", 0, AV_OPT_TYPE_CONST, {.i64=CYAN}, 0, 0, VF, "colors" }, + { "b", "set blues", 0, AV_OPT_TYPE_CONST, {.i64=BLUE}, 0, 0, VF, "colors" }, + { "m", "set magentas", 0, AV_OPT_TYPE_CONST, {.i64=MAGENTA}, 0, 0, VF, "colors" }, + { "a", "set all colors", 0, AV_OPT_TYPE_CONST, {.i64=ALL}, 0, 0, VF, "colors" }, + { "strength", "set the filtering strength", OFFSET(strength), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0,100,VF }, + { "rw", "set the red weight", OFFSET(rlw), AV_OPT_TYPE_FLOAT, {.dbl=.333}, 0, 1, VF }, + { "gw", "set the green weight", OFFSET(glw), AV_OPT_TYPE_FLOAT, {.dbl=.334}, 0, 1, VF }, + { "bw", "set the blue weight", OFFSET(blw), AV_OPT_TYPE_FLOAT, {.dbl=.333}, 0, 1, VF }, + { "lightness", "set the preserve lightness", OFFSET(lightness), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, VF }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(huesaturation); + +const AVFilter ff_vf_huesaturation = { + .name = "huesaturation", + .description = NULL_IF_CONFIG_SMALL("Apply hue-saturation-intensity adjustments."), + .priv_size = sizeof(HueSaturationContext), + .priv_class = &huesaturation_class, + FILTER_INPUTS(huesaturation_inputs), + FILTER_OUTPUTS(huesaturation_outputs), + FILTER_PIXFMTS_ARRAY(pixel_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = ff_filter_process_command, +}; diff --git a/libavfilter/vf_identity.c b/libavfilter/vf_identity.c index 5096bda382..cc30761388 100644 --- a/libavfilter/vf_identity.c +++ b/libavfilter/vf_identity.c @@ -412,7 +412,9 @@ const AVFilter ff_vf_identity = { FILTER_INPUTS(identity_inputs), FILTER_OUTPUTS(identity_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_IDENTITY_FILTER */ @@ -434,7 +436,9 @@ const AVFilter ff_vf_msad = { FILTER_INPUTS(identity_inputs), FILTER_OUTPUTS(identity_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; #endif /* CONFIG_MSAD_FILTER */ diff --git a/libavfilter/vf_idet.c b/libavfilter/vf_idet.c index 0f3e78c4ec..9320b485d8 100644 --- a/libavfilter/vf_idet.c +++ b/libavfilter/vf_idet.c @@ -436,6 +436,7 @@ const AVFilter ff_vf_idet = { .priv_size = sizeof(IDETContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(idet_inputs), FILTER_OUTPUTS(idet_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c new file mode 100644 index 0000000000..31ae28ac38 --- /dev/null +++ b/libavfilter/vf_libplacebo.c @@ -0,0 +1,695 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/file.h" +#include "libavutil/opt.h" +#include "internal.h" +#include "vulkan_filter.h" +#include "scale_eval.h" + +#include +#include +#include + +typedef struct LibplaceboContext { + /* lavfi vulkan*/ + FFVulkanContext vkctx; + int initialized; + + /* libplacebo */ + pl_log log; + pl_vulkan vulkan; + pl_gpu gpu; + pl_renderer renderer; + + /* settings */ + char *out_format_string; + char *w_expr; + char *h_expr; + AVRational target_sar; + float pad_crop_ratio; + int force_original_aspect_ratio; + int force_divisible_by; + int normalize_sar; + int apply_filmgrain; + int apply_dovi; + int colorspace; + int color_range; + int color_primaries; + int color_trc; + + /* pl_render_params */ + char *upscaler; + char *downscaler; + int lut_entries; + float antiringing; + int sigmoid; + int skip_aa; + float polar_cutoff; + int disable_linear; + int disable_builtin; + int force_icc_lut; + int force_dither; + int disable_fbos; + + /* pl_deband_params */ + int deband; + int deband_iterations; + float deband_threshold; + float deband_radius; + float deband_grain; + + /* pl_color_adjustment */ + float brightness; + float contrast; + float saturation; + float hue; + float gamma; + + /* pl_peak_detect_params */ + int peakdetect; + float smoothing; + float min_peak; + float scene_low; + float scene_high; + float overshoot; + + /* pl_color_map_params */ + int intent; + int tonemapping; + float tonemapping_param; + float desat_str; + float desat_exp; + float desat_base; + float max_boost; + int gamut_warning; + int gamut_clipping; + + /* pl_dither_params */ + int dithering; + int dither_lut_size; + int dither_temporal; + + /* pl_cone_params */ + int cones; + float cone_str; + + /* custom shaders */ + char *shader_path; + void *shader_bin; + int shader_bin_len; + const struct pl_hook *hooks[2]; + int num_hooks; +} LibplaceboContext; + +static inline enum pl_log_level get_log_level(void) +{ + int av_lev = av_log_get_level(); + return av_lev >= AV_LOG_TRACE ? PL_LOG_TRACE : + av_lev >= AV_LOG_DEBUG ? PL_LOG_DEBUG : + av_lev >= AV_LOG_VERBOSE ? PL_LOG_INFO : + av_lev >= AV_LOG_WARNING ? PL_LOG_WARN : + av_lev >= AV_LOG_ERROR ? PL_LOG_ERR : + av_lev >= AV_LOG_FATAL ? PL_LOG_FATAL : + PL_LOG_NONE; +} + +static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg) +{ + int av_lev; + + switch (level) { + case PL_LOG_FATAL: av_lev = AV_LOG_FATAL; break; + case PL_LOG_ERR: av_lev = AV_LOG_ERROR; break; + case PL_LOG_WARN: av_lev = AV_LOG_WARNING; break; + case PL_LOG_INFO: av_lev = AV_LOG_VERBOSE; break; + case PL_LOG_DEBUG: av_lev = AV_LOG_DEBUG; break; + case PL_LOG_TRACE: av_lev = AV_LOG_TRACE; break; + default: return; + } + + av_log(log_ctx, av_lev, "%s\n", msg); +} + +static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len) +{ + LibplaceboContext *s = avctx->priv; + const struct pl_hook *hook; + + hook = pl_mpv_user_shader_parse(s->gpu, shader, len); + if (!hook) { + av_log(s, AV_LOG_ERROR, "Failed parsing custom shader!\n"); + return AVERROR(EINVAL); + } + + s->hooks[s->num_hooks++] = hook; + return 0; +} + +static int find_scaler(AVFilterContext *avctx, + const struct pl_filter_config **opt, + const char *name) +{ + const struct pl_filter_preset *preset; + if (!strcmp(name, "help")) { + av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n"); + for (preset = pl_scale_filters; preset->name; preset++) + av_log(avctx, AV_LOG_INFO, " %s\n", preset->name); + return AVERROR_EXIT; + } + + for (preset = pl_scale_filters; preset->name; preset++) { + if (!strcmp(name, preset->name)) { + *opt = preset->filter; + return 0; + } + } + + av_log(avctx, AV_LOG_ERROR, "No such scaler preset '%s'.\n", name); + return AVERROR(EINVAL); +} + +static int libplacebo_init(AVFilterContext *avctx) +{ + LibplaceboContext *s = avctx->priv; + + /* Create libplacebo log context */ + s->log = pl_log_create(PL_API_VER, pl_log_params( + .log_level = get_log_level(), + .log_cb = pl_av_log, + .log_priv = s, + )); + + if (!s->log) + return AVERROR(ENOMEM); + + /* Note: s->vulkan etc. are initialized later, when hwctx is available */ + return 0; +} + +static int init_vulkan(AVFilterContext *avctx) +{ + int err = 0; + LibplaceboContext *s = avctx->priv; + const AVVulkanDeviceContext *hwctx = s->vkctx.hwctx; + uint8_t *buf = NULL; + size_t buf_len; + + /* Import libavfilter vulkan context into libplacebo */ + s->vulkan = pl_vulkan_import(s->log, pl_vulkan_import_params( + .instance = hwctx->inst, + .get_proc_addr = hwctx->get_proc_addr, + .phys_device = hwctx->phys_dev, + .device = hwctx->act_dev, + .extensions = hwctx->enabled_dev_extensions, + .num_extensions = hwctx->nb_enabled_dev_extensions, + .features = &hwctx->device_features, + .queue_graphics = { + .index = hwctx->queue_family_index, + .count = hwctx->nb_graphics_queues, + }, + .queue_compute = { + .index = hwctx->queue_family_comp_index, + .count = hwctx->nb_comp_queues, + }, + .queue_transfer = { + .index = hwctx->queue_family_tx_index, + .count = hwctx->nb_tx_queues, + }, + /* This is the highest version created by hwcontext_vulkan.c */ + .max_api_version = VK_API_VERSION_1_2, + )); + + if (!s->vulkan) { + av_log(s, AV_LOG_ERROR, "Failed importing vulkan device to libplacebo!\n"); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Create the renderer */ + s->gpu = s->vulkan->gpu; + s->renderer = pl_renderer_create(s->log, s->gpu); + + /* Parse the user shaders, if requested */ + if (s->shader_bin_len) + RET(parse_shader(avctx, s->shader_bin, s->shader_bin_len)); + + if (s->shader_path && s->shader_path[0]) { + RET(av_file_map(s->shader_path, &buf, &buf_len, 0, s)); + RET(parse_shader(avctx, buf, buf_len)); + } + + /* fall through */ +fail: + if (buf) + av_file_unmap(buf, buf_len); + s->initialized = 1; + return err; +} + +static void libplacebo_uninit(AVFilterContext *avctx) +{ + LibplaceboContext *s = avctx->priv; + + for (int i = 0; i < s->num_hooks; i++) + pl_mpv_user_shader_destroy(&s->hooks[i]); + pl_renderer_destroy(&s->renderer); + pl_vulkan_destroy(&s->vulkan); + pl_log_destroy(&s->log); + ff_vk_uninit(&s->vkctx); + s->initialized = 0; + s->gpu = NULL; +} + +static int process_frames(AVFilterContext *avctx, AVFrame *out, AVFrame *in) +{ + int err = 0, ok; + LibplaceboContext *s = avctx->priv; + struct pl_render_params params; + struct pl_frame image, target; + ok = pl_map_avframe_ex(s->gpu, &image, pl_avframe_params( + .frame = in, + .map_dovi = s->apply_dovi, + )); + + ok &= pl_map_avframe_ex(s->gpu, &target, pl_avframe_params( + .frame = out, + .map_dovi = false, + )); + + if (!ok) { + err = AVERROR_EXTERNAL; + goto fail; + } + + if (!s->apply_filmgrain) + image.film_grain.type = PL_FILM_GRAIN_NONE; + + if (s->target_sar.num) { + float aspect = pl_rect2df_aspect(&target.crop) * av_q2d(s->target_sar); + pl_rect2df_aspect_set(&target.crop, aspect, s->pad_crop_ratio); + } + + /* Update render params */ + params = (struct pl_render_params) { + PL_RENDER_DEFAULTS + .lut_entries = s->lut_entries, + .antiringing_strength = s->antiringing, + + .deband_params = !s->deband ? NULL : pl_deband_params( + .iterations = s->deband_iterations, + .threshold = s->deband_threshold, + .radius = s->deband_radius, + .grain = s->deband_grain, + ), + + .sigmoid_params = s->sigmoid ? &pl_sigmoid_default_params : NULL, + + .color_adjustment = &(struct pl_color_adjustment) { + .brightness = s->brightness, + .contrast = s->contrast, + .saturation = s->saturation, + .hue = s->hue, + .gamma = s->gamma, + }, + + .peak_detect_params = !s->peakdetect ? NULL : pl_peak_detect_params( + .smoothing_period = s->smoothing, + .minimum_peak = s->min_peak, + .scene_threshold_low = s->scene_low, + .scene_threshold_high = s->scene_high, + .overshoot_margin = s->overshoot, + ), + + .color_map_params = pl_color_map_params( + .intent = s->intent, + .tone_mapping_algo = 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, + ), + + .dither_params = s->dithering < 0 ? NULL : pl_dither_params( + .method = s->dithering, + .lut_size = s->dither_lut_size, + .temporal = s->dither_temporal, + ), + + .cone_params = !s->cones ? NULL : pl_cone_params( + .cones = s->cones, + .strength = s->cone_str, + ), + + .hooks = s->hooks, + .num_hooks = s->num_hooks, + + .skip_anti_aliasing = s->skip_aa, + .polar_cutoff = s->polar_cutoff, + .disable_linear_scaling = s->disable_linear, + .disable_builtin_scalers = s->disable_builtin, + .force_icc_lut = s->force_icc_lut, + .force_dither = s->force_dither, + .disable_fbos = s->disable_fbos, + }; + + RET(find_scaler(avctx, ¶ms.upscaler, s->upscaler)); + RET(find_scaler(avctx, ¶ms.downscaler, s->downscaler)); + + pl_render_image(s->renderer, &image, &target, ¶ms); + pl_unmap_avframe(s->gpu, &image); + pl_unmap_avframe(s->gpu, &target); + + /* Flush the command queues for performance */ + pl_gpu_flush(s->gpu); + return 0; + +fail: + pl_unmap_avframe(s->gpu, &image); + pl_unmap_avframe(s->gpu, &target); + return err; +} + +static int filter_frame(AVFilterLink *link, AVFrame *in) +{ + int err, changed_csp; + AVFilterContext *ctx = link->dst; + LibplaceboContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + pl_log_level_update(s->log, get_log_level()); + if (!s->initialized) + RET(init_vulkan(ctx)); + + RET(av_frame_copy_props(out, in)); + out->width = outlink->w; + out->height = outlink->h; + + if (s->apply_dovi && av_frame_get_side_data(in, AV_FRAME_DATA_DOVI_METADATA)) { + /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct + * output colorspace defaults */ + out->colorspace = AVCOL_SPC_BT2020_NCL; + out->color_primaries = AVCOL_PRI_BT2020; + out->color_trc = AVCOL_TRC_SMPTE2084; + } + + if (s->colorspace >= 0) + out->colorspace = s->colorspace; + if (s->color_range >= 0) + out->color_range = s->color_range; + if (s->color_trc >= 0) + out->color_trc = s->color_trc; + if (s->color_primaries >= 0) + out->color_primaries = s->color_primaries; + + changed_csp = in->colorspace != out->colorspace || + in->color_range != out->color_range || + in->color_trc != out->color_trc || + in->color_primaries != out->color_primaries; + + /* Strip side data if no longer relevant */ + if (changed_csp) { + av_frame_remove_side_data(out, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + av_frame_remove_side_data(out, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + } + if (s->apply_dovi || changed_csp) { + av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_RPU_BUFFER); + av_frame_remove_side_data(out, AV_FRAME_DATA_DOVI_METADATA); + } + if (s->apply_filmgrain) + av_frame_remove_side_data(out, AV_FRAME_DATA_FILM_GRAIN_PARAMS); + + RET(process_frames(ctx, out, in)); + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static int libplacebo_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + LibplaceboContext *s = avctx->priv; + AVFilterLink *inlink = outlink->src->inputs[0]; + AVHWFramesContext *hwfc; + AVVulkanFramesContext *vkfc; + AVRational scale_sar; + int *out_w = &s->vkctx.output_width; + int *out_h = &s->vkctx.output_height; + + RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, + out_w, out_h)); + + ff_scale_adjust_dimensions(inlink, out_w, out_h, + s->force_original_aspect_ratio, + s->force_divisible_by); + + scale_sar = (AVRational){outlink->h * inlink->w, *out_w * *out_h}; + if (inlink->sample_aspect_ratio.num) + scale_sar = av_mul_q(scale_sar, inlink->sample_aspect_ratio); + + if (s->normalize_sar) { + /* Apply all SAR during scaling, so we don't need to set the out SAR */ + s->target_sar = scale_sar; + } else { + /* This is consistent with other scale_* filters, which only + * set the outlink SAR to be equal to the scale SAR iff the input SAR + * was set to something nonzero */ + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = scale_sar; + } + + if (s->out_format_string) { + s->vkctx.output_format = av_get_pix_fmt(s->out_format_string); + if (s->vkctx.output_format == AV_PIX_FMT_NONE) { + av_log(avctx, AV_LOG_ERROR, "Invalid output format.\n"); + return AVERROR(EINVAL); + } + } else { + /* Default to re-using the input format */ + s->vkctx.output_format = s->vkctx.input_format; + } + + RET(ff_vk_filter_config_output(outlink)); + hwfc = (AVHWFramesContext *) outlink->hw_frames_ctx->data; + vkfc = hwfc->hwctx; + vkfc->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + return 0; + +fail: + return err; +} + +#define OFFSET(x) offsetof(LibplaceboContext, x) +#define STATIC (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) +#define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM) + +static const AVOption libplacebo_options[] = { + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC }, + { "format", "Output video format", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = STATIC }, + { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, STATIC, "force_oar" }, + { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, STATIC, "force_oar" }, + { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, STATIC, "force_oar" }, + { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, STATIC, "force_oar" }, + { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, STATIC }, + { "normalize_sar", "force SAR normalization to 1:1", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, STATIC }, + { "pad_crop_ratio", "ratio between padding and cropping when normalizing SAR (0=pad, 1=crop)", OFFSET(pad_crop_ratio), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, 1.0, DYNAMIC }, + + {"colorspace", "select colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_NB-1, DYNAMIC, "colorspace"}, + {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"gbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_RGB}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"ycgco", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_YCGCO}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt2020nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"bt2020c", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_CL}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + {"ictcp", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_ICTCP}, INT_MIN, INT_MAX, STATIC, "colorspace"}, + + {"range", "select color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_RANGE_NB-1, DYNAMIC, "range"}, + {"auto", "keep the same color range", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, "range"}, + {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, "range"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, "range"}, + {"limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, "range"}, + {"full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + {"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + {"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, "range"}, + + {"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_NB-1, DYNAMIC, "color_primaries"}, + {"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, STATIC, "color_primaries"}, + + {"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_NB-1, DYNAMIC, "color_trc"}, + {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, STATIC, "color_trc"}, + + { "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC }, + { "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC }, + { "lut_entries", "Number of scaler LUT entries", OFFSET(lut_entries), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 256, DYNAMIC }, + { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC }, + { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "apply_filmgrain", "Apply film grain metadata", OFFSET(apply_filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "apply_dolbyvision", "Apply Dolby Vision metadata", OFFSET(apply_dovi), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + + { "deband", "Enable debanding", OFFSET(deband), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "deband_iterations", "Deband iterations", OFFSET(deband_iterations), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 16, DYNAMIC }, + { "deband_threshold", "Deband threshold", OFFSET(deband_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 4.0}, 0.0, 1024.0, DYNAMIC }, + { "deband_radius", "Deband radius", OFFSET(deband_radius), AV_OPT_TYPE_FLOAT, {.dbl = 16.0}, 0.0, 1024.0, DYNAMIC }, + { "deband_grain", "Deband grain", OFFSET(deband_grain), AV_OPT_TYPE_FLOAT, {.dbl = 6.0}, 0.0, 1024.0, DYNAMIC }, + + { "brightness", "Brightness boost", OFFSET(brightness), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -1.0, 1.0, DYNAMIC }, + { "contrast", "Contrast gain", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + { "saturation", "Saturation gain", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + { "hue", "Hue shift", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -M_PI, M_PI, DYNAMIC }, + { "gamma", "Gamma adjustment", OFFSET(gamma), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC }, + + { "peak_detect", "Enable dynamic peak detection for HDR tone-mapping", OFFSET(peakdetect), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC }, + { "smoothing_period", "Peak detection smoothing period", OFFSET(smoothing), AV_OPT_TYPE_FLOAT, {.dbl = 100.0}, 0.0, 1000.0, DYNAMIC }, + { "minimum_peak", "Peak detection minimum peak", OFFSET(min_peak), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 100.0, DYNAMIC }, + { "scene_threshold_low", "Scene change low threshold", OFFSET(scene_low), AV_OPT_TYPE_FLOAT, {.dbl = 5.5}, -1.0, 100.0, DYNAMIC }, + { "scene_threshold_high", "Scene change high threshold", OFFSET(scene_high), AV_OPT_TYPE_FLOAT, {.dbl = 10.0}, -1.0, 100.0, DYNAMIC }, + { "overshoot", "Tone-mapping overshoot margin", OFFSET(overshoot), AV_OPT_TYPE_FLOAT, {.dbl = 0.05}, 0.0, 1.0, DYNAMIC }, + + { "intent", "Rendering intent", OFFSET(intent), AV_OPT_TYPE_INT, {.i64 = PL_INTENT_RELATIVE_COLORIMETRIC}, 0, 3, DYNAMIC, "intent" }, + { "perceptual", "Perceptual", 0, AV_OPT_TYPE_CONST, {.i64 = PL_INTENT_PERCEPTUAL}, 0, 0, STATIC, "intent" }, + { "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" }, + { "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 }, + + { "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" }, + { "blue", "Blue noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_BLUE_NOISE}, 0, 0, STATIC, "dither" }, + { "ordered", "Ordered LUT", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_LUT}, 0, 0, STATIC, "dither" }, + { "ordered_fixed", "Fixed function ordered", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_FIXED}, 0, 0, STATIC, "dither" }, + { "white", "White noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_WHITE_NOISE}, 0, 0, STATIC, "dither" }, + { "dither_lut_size", "Dithering LUT size", OFFSET(dither_lut_size), AV_OPT_TYPE_INT, {.i64 = 6}, 1, 8, STATIC }, + { "dither_temporal", "Enable temporal dithering", OFFSET(dither_temporal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + + { "cones", "Colorblindness adaptation model", OFFSET(cones), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, PL_CONE_LMS, DYNAMIC, "cone" }, + { "l", "L cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_L}, 0, 0, STATIC, "cone" }, + { "m", "M cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_M}, 0, 0, STATIC, "cone" }, + { "s", "S cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_S}, 0, 0, STATIC, "cone" }, + { "cone-strength", "Colorblindness adaptation strength", OFFSET(cone_str), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 10.0, DYNAMIC }, + + { "custom_shader_path", "Path to custom user shader (mpv .hook format)", OFFSET(shader_path), AV_OPT_TYPE_STRING, .flags = STATIC }, + { "custom_shader_bin", "Custom user shader as binary (mpv .hook format)", OFFSET(shader_bin), AV_OPT_TYPE_BINARY, .flags = STATIC }, + + /* 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 }, + { "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 }, + { "force_dither", "Force dithering", OFFSET(force_dither), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { "disable_fbos", "Force-disable FBOs", OFFSET(disable_fbos), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC }, + { NULL }, +}; + +AVFILTER_DEFINE_CLASS(libplacebo); + +static const AVFilterPad libplacebo_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &filter_frame, + .config_props = &ff_vk_filter_config_input, + }, +}; + +static const AVFilterPad libplacebo_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &libplacebo_config_output, + }, +}; + +AVFilter ff_vf_libplacebo = { + .name = "libplacebo", + .description = NULL_IF_CONFIG_SMALL("Apply various GPU filters from libplacebo"), + .priv_size = sizeof(LibplaceboContext), + .init = &libplacebo_init, + .uninit = &libplacebo_uninit, + .process_command = &ff_filter_process_command, + FILTER_INPUTS(libplacebo_inputs), + FILTER_OUTPUTS(libplacebo_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &libplacebo_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index 64668039d1..fd5b364797 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -69,7 +69,6 @@ typedef struct LutContext { int is_planar; int is_16bit; int step; - int negate_alpha; /* only used by negate */ } LutContext; #define Y 0 @@ -642,30 +641,3 @@ static av_cold int lutrgb_init(AVFilterContext *ctx) DEFINE_LUT_FILTER(lutrgb, "Compute and apply a lookup table to the RGB input video.", lut); #endif - -#if CONFIG_NEGATE_FILTER - -static const AVOption negate_options[] = { - { "negate_alpha", NULL, OFFSET(negate_alpha), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, - { NULL } -}; - -AVFILTER_DEFINE_CLASS(negate); - -static av_cold int negate_init(AVFilterContext *ctx) -{ - LutContext *s = ctx->priv; - - for (int i = 0; i < 4; i++) { - s->comp_expr_str[i] = av_strdup((i == 3 && !s->negate_alpha) ? - "val" : "negval"); - if (!s->comp_expr_str[i]) - return AVERROR(ENOMEM); - } - - return 0; -} - -DEFINE_LUT_FILTER(negate, "Negate input video.", negate); - -#endif diff --git a/libavfilter/vf_mestimate.c b/libavfilter/vf_mestimate.c index d8bcfdde02..eff58f612e 100644 --- a/libavfilter/vf_mestimate.c +++ b/libavfilter/vf_mestimate.c @@ -363,6 +363,7 @@ const AVFilter ff_vf_mestimate = { .priv_size = sizeof(MEContext), .priv_class = &mestimate_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(mestimate_inputs), FILTER_OUTPUTS(mestimate_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_negate.c b/libavfilter/vf_negate.c new file mode 100644 index 0000000000..d782e63d3a --- /dev/null +++ b/libavfilter/vf_negate.c @@ -0,0 +1,375 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/imgutils.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "avfilter.h" +#include "drawutils.h" +#include "formats.h" +#include "internal.h" +#include "video.h" + +#define COMP_R 0x01 +#define COMP_G 0x02 +#define COMP_B 0x04 +#define COMP_A 0x08 +#define COMP_Y 0x10 +#define COMP_U 0x20 +#define COMP_V 0x40 + +typedef struct ThreadData { + AVFrame *in; + AVFrame *out; +} ThreadData; + +typedef struct NegateContext { + const AVClass *class; + int negate_alpha; + int max; + int requested_components; + int components; + int planes; + int step; + int nb_planes; + int linesize[4]; + int width[4]; + int height[4]; + uint8_t rgba_map[4]; + + void (*negate)(const uint8_t *src, uint8_t *dst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components); +} NegateContext; + +#define OFFSET(x) offsetof(NegateContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM + +static const AVOption negate_options[] = { + { "components", "set components to negate", OFFSET(requested_components), AV_OPT_TYPE_FLAGS, {.i64=0x77}, 1, 0xff, FLAGS, "flags"}, + { "y", "set luma component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_Y}, 0, 0, FLAGS, "flags"}, + { "u", "set u component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_U}, 0, 0, FLAGS, "flags"}, + { "v", "set v component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_V}, 0, 0, FLAGS, "flags"}, + { "r", "set red component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_R}, 0, 0, FLAGS, "flags"}, + { "g", "set green component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_G}, 0, 0, FLAGS, "flags"}, + { "b", "set blue component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_B}, 0, 0, FLAGS, "flags"}, + { "a", "set alpha component", 0, AV_OPT_TYPE_CONST, {.i64=COMP_A}, 0, 0, FLAGS, "flags"}, + { "negate_alpha", NULL, OFFSET(negate_alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(negate); + +static const enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV440P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P, + AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P, + AV_PIX_FMT_YUVJ440P, + AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV422P9, AV_PIX_FMT_YUV420P9, + AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV440P10, + AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV422P12, AV_PIX_FMT_YUV420P12, AV_PIX_FMT_YUV440P12, + AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV422P14, AV_PIX_FMT_YUV420P14, + AV_PIX_FMT_YUV444P16, AV_PIX_FMT_YUV422P16, AV_PIX_FMT_YUV420P16, + AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_YUVA422P16, AV_PIX_FMT_YUVA420P16, + AV_PIX_FMT_ARGB, AV_PIX_FMT_RGBA, + AV_PIX_FMT_ABGR, AV_PIX_FMT_BGRA, + AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24, + AV_PIX_FMT_RGB48, AV_PIX_FMT_RGBA64, + AV_PIX_FMT_BGR48, AV_PIX_FMT_BGRA64, + 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_GBRP14, + AV_PIX_FMT_GBRP16, 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_NONE +}; + +static void negate8(const uint8_t *src, uint8_t *dst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = 255 - src[x]; + + dst += dlinesize; + src += slinesize; + } +} + +static void negate_packed8(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + const uint8_t *src = ssrc + y * slinesize; + uint8_t *dst = ddst + y * dlinesize; + + for (int x = 0; x < w; x++) { + switch (step) { + case 4: dst[3] = components & 8 ? 255 - src[3] : src[3]; + case 3: dst[2] = components & 4 ? 255 - src[2] : src[2]; + case 2: dst[1] = components & 2 ? 255 - src[1] : src[1]; + default: dst[0] = components & 1 ? 255 - src[0] : src[0]; + } + + src += step; + dst += step; + } + } +} + +static void negate16(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + const uint16_t *src = (const uint16_t *)ssrc; + uint16_t *dst = (uint16_t *)ddst; + + dlinesize /= 2; + slinesize /= 2; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) + dst[x] = max - src[x]; + + dst += dlinesize; + src += slinesize; + } +} + +static void negate_packed16(const uint8_t *ssrc, uint8_t *ddst, + ptrdiff_t slinesize, ptrdiff_t dlinesize, + int w, int h, int max, int step, + int components) +{ + for (int y = 0; y < h; y++) { + const uint16_t *src = (const uint16_t *)(ssrc + y * slinesize); + uint16_t *dst = (uint16_t *)(ddst + y * dlinesize); + + for (int x = 0; x < w; x++) { + switch (step) { + case 4: dst[3] = components & 8 ? max - src[3] : src[3]; + case 3: dst[2] = components & 4 ? max - src[2] : src[2]; + case 2: dst[1] = components & 2 ? max - src[1] : src[1]; + default: dst[0] = components & 1 ? max - src[0] : src[0]; + } + + src += step; + dst += step; + } + } +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + NegateContext *s = ctx->priv; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); + int depth, vsub, hsub, ret, is_packed; + int comp_avail; + + s->planes = s->negate_alpha ? 0xF : 0x7; + is_packed = !(desc->flags & AV_PIX_FMT_FLAG_PLANAR) && + (desc->nb_components > 1); + if (s->requested_components != 0x77) { + comp_avail = ((desc->flags & AV_PIX_FMT_FLAG_RGB) ? COMP_R|COMP_G|COMP_B : + COMP_Y | + ((desc->nb_components > 2) ? COMP_U|COMP_V : 0)) | + ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) ? COMP_A : 0); + if (s->requested_components & ~comp_avail) { + av_log(ctx, AV_LOG_ERROR, "Requested components not available.\n"); + return AVERROR(EINVAL); + } + + s->planes = 0; + if (!(desc->flags & AV_PIX_FMT_FLAG_RGB)) { + if (s->requested_components & COMP_Y) + s->planes |= 1; + if (s->requested_components & COMP_U) + s->planes |= 2; + if (s->requested_components & COMP_V) + s->planes |= 4; + if (s->requested_components & COMP_A) + s->planes |= 8; + } else { + if (s->requested_components & COMP_R) + s->planes |= 4; + if (s->requested_components & COMP_G) + s->planes |= 1; + if (s->requested_components & COMP_B) + s->planes |= 2; + if (s->requested_components & COMP_A) + s->planes |= 8; + } + } + s->nb_planes = av_pix_fmt_count_planes(inlink->format); + + s->components = 0; + if (desc->flags & AV_PIX_FMT_FLAG_RGB) { + ff_fill_rgba_map(s->rgba_map, inlink->format); + + if (s->requested_components & COMP_R) + s->components |= 1 << s->rgba_map[0]; + if (s->requested_components & COMP_G) + s->components |= 1 << s->rgba_map[1]; + if (s->requested_components & COMP_B) + s->components |= 1 << s->rgba_map[2]; + if (s->requested_components & COMP_A) + s->components |= 1 << s->rgba_map[3]; + } + + if ((ret = av_image_fill_linesizes(s->linesize, inlink->format, inlink->w)) < 0) + return ret; + + depth = desc->comp[0].depth; + 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->negate = depth <= 8 ? negate8 : negate16; + if (is_packed) { + s->negate = depth <= 8 ? negate_packed8 : negate_packed16; + s->planes = 1; + } + s->max = (1 << depth) - 1; + s->step = av_get_bits_per_pixel(desc) >> 3; + if (depth > 8) + s->step = s->step >> 1; + + return 0; +} + +static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + NegateContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + for (int p = 0; p < s->nb_planes; p++) { + const int h = s->height[p]; + const int slice_start = (h * jobnr) / nb_jobs; + const int slice_end = (h * (jobnr+1)) / nb_jobs; + + if (!((1 << p) & s->planes)) { + if (out != in) + av_image_copy_plane(out->data[p] + slice_start * out->linesize[p], + out->linesize[p], + in->data[p] + slice_start * in->linesize[p], + in->linesize[p], + s->linesize[p], slice_end - slice_start); + continue; + } + + s->negate(in->data[p] + slice_start * in->linesize[p], + out->data[p] + slice_start * out->linesize[p], + in->linesize[p], out->linesize[p], + s->width[p], slice_end - slice_start, + s->max, s->step, s->components); + } + + return 0; +} + +static int filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + AVFilterContext *ctx = inlink->dst; + NegateContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; + AVFrame *out; + + 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.out = out; + td.in = in; + ff_filter_execute(ctx, filter_slice, &td, NULL, + FFMIN(s->height[2], ff_filter_get_nb_threads(ctx))); + if (out != in) + av_frame_free(&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) +{ + NegateContext *s = ctx->priv; + int old_planes = s->planes; + int ret; + + ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); + if (ret < 0) + return ret; + + ret = config_input(ctx->inputs[0]); + if (ret < 0) + s->planes = old_planes; + return ret; +} + +static const AVFilterPad inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + }, +}; + +const AVFilter ff_vf_negate = { + .name = "negate", + .description = NULL_IF_CONFIG_SMALL("Negate input video."), + .priv_size = sizeof(NegateContext), + .priv_class = &negate_class, + FILTER_INPUTS(inputs), + FILTER_OUTPUTS(outputs), + FILTER_PIXFMTS_ARRAY(pix_fmts), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .process_command = process_command, +}; diff --git a/libavfilter/vf_nlmeans.c b/libavfilter/vf_nlmeans.c index 74fc3923b3..8a05965c9b 100644 --- a/libavfilter/vf_nlmeans.c +++ b/libavfilter/vf_nlmeans.c @@ -38,11 +38,6 @@ #include "vf_nlmeans.h" #include "video.h" -struct weighted_avg { - float total_weight; - float sum; -}; - typedef struct NLMeansContext { const AVClass *class; int nb_planes; @@ -57,8 +52,9 @@ typedef struct NLMeansContext { uint32_t *ii; // integral image starting after the 0-line and 0-column int ii_w, ii_h; // width and height of the integral image ptrdiff_t ii_lz_32; // linesize in 32-bit units of the integral image - struct weighted_avg *wa; // weighted average of every pixel - ptrdiff_t wa_linesize; // linesize for wa in struct size unit + float *total_weight; // total weight for every pixel + float *sum; // weighted sum for every pixel + int linesize; // sum and total_weight linesize float *weight_lut; // lookup table mapping (scaled) patch differences to their associated weights uint32_t max_meaningful_diff; // maximum difference considered (if the patch difference is too high we ignore the pixel) NLMeansDSPContext dsp; @@ -101,14 +97,13 @@ static void compute_safe_ssd_integral_image_c(uint32_t *dst, ptrdiff_t dst_lines const uint8_t *s2, ptrdiff_t linesize2, int w, int h) { - int x, y; const uint32_t *dst_top = dst - dst_linesize_32; /* SIMD-friendly assumptions allowed here */ av_assert2(!(w & 0xf) && w >= 16 && h >= 1); - for (y = 0; y < h; y++) { - for (x = 0; x < w; x += 4) { + 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]; @@ -161,14 +156,12 @@ static inline void compute_unsafe_ssd_integral_image(uint32_t *dst, ptrdiff_t ds int offx, int offy, int r, int sw, int sh, int w, int h) { - int x, y; - - for (y = starty; y < starty + h; y++) { + for (int y = starty; y < starty + h; y++) { uint32_t acc = dst[y*dst_linesize_32 + startx - 1] - dst[(y-1)*dst_linesize_32 + startx - 1]; const int s1y = av_clip(y - r, 0, sh - 1); const int s2y = av_clip(y - (r + offy), 0, sh - 1); - for (x = startx; x < startx + w; x++) { + for (int x = startx; x < startx + w; x++) { const int s1x = av_clip(x - r, 0, sw - 1); const int s2x = av_clip(x - (r + offx), 0, sw - 1); const uint8_t v1 = src[s1y*linesize + s1x]; @@ -315,9 +308,10 @@ static int config_input(AVFilterLink *inlink) s->ii = s->ii_orig + s->ii_lz_32 + 1; // allocate weighted average for every pixel - s->wa_linesize = inlink->w; - s->wa = av_malloc_array(s->wa_linesize, inlink->h * sizeof(*s->wa)); - if (!s->wa) + s->linesize = inlink->w + 100; + s->total_weight = av_malloc_array(s->linesize, inlink->h * sizeof(*s->total_weight)); + s->sum = av_malloc_array(s->linesize, inlink->h * sizeof(*s->sum)); + if (!s->total_weight || !s->sum) return AVERROR(ENOMEM); return 0; @@ -332,10 +326,63 @@ 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) { - int x, y; NLMeansContext *s = ctx->priv; + const uint32_t max_meaningful_diff = s->max_meaningful_diff; const struct thread_data *td = arg; const ptrdiff_t src_linesize = td->src_linesize; const int process_h = td->endy - td->starty; @@ -348,52 +395,21 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs const int dist_b = 2*p + 1; const int dist_d = dist_b * s->ii_lz_32; const int dist_e = dist_d + dist_b; + const float *const weight_lut = s->weight_lut; + NLMeansDSPContext *dsp = &s->dsp; - for (y = starty; y < endy; y++) { - const uint8_t *src = td->src + y*src_linesize; - struct weighted_avg *wa = s->wa + y*s->wa_linesize; - for (x = td->startx; x < td->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 = ii[x]; - const uint32_t b = ii[x + dist_b]; - const uint32_t d = ii[x + dist_d]; - const uint32_t e = ii[x + dist_e]; - const uint32_t patch_diff_sq = e - d - b + a; + for (int y = starty; y < endy; y++) { + const uint8_t *const src = td->src + y*src_linesize; + float *total_weight = s->total_weight + y*s->linesize; + float *sum = s->sum + y*s->linesize; + const uint32_t *const iia = ii; + const uint32_t *const iib = ii + dist_b; + const uint32_t *const iid = ii + dist_d; + const uint32_t *const iie = ii + dist_e; - if (patch_diff_sq < s->max_meaningful_diff) { - const float weight = s->weight_lut[patch_diff_sq]; // exp(-patch_diff_sq * s->pdiff_scale) - wa[x].total_weight += weight; - wa[x].sum += weight * src[x]; - } - } + dsp->compute_weights_line(iia, iib, iid, iie, src, total_weight, sum, + weight_lut, max_meaningful_diff, + td->startx, td->endx); ii += s->ii_lz_32; } return 0; @@ -401,21 +417,20 @@ static int nlmeans_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs static void weight_averages(uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize, - struct weighted_avg *wa, ptrdiff_t wa_linesize, + float *total_weight, float *sum, ptrdiff_t linesize, int w, int h) { - int x, y; - - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { // Also weight the centered pixel - wa[x].total_weight += 1.f; - wa[x].sum += 1.f * src[x]; - dst[x] = av_clip_uint8(wa[x].sum / wa[x].total_weight + 0.5f); + total_weight[x] += 1.f; + sum[x] += 1.f * src[x]; + dst[x] = av_clip_uint8(sum[x] / total_weight[x] + 0.5f); } dst += dst_linesize; src += src_linesize; - wa += wa_linesize; + total_weight += linesize; + sum += linesize; } } @@ -423,7 +438,6 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, uint8_t *dst, ptrdiff_t dst_linesize, const uint8_t *src, ptrdiff_t src_linesize) { - int offx, offy; NLMeansContext *s = ctx->priv; /* patches center points cover the whole research window so the patches * themselves overflow the research window */ @@ -431,10 +445,11 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, /* focus an integral pointer on the centered image (s1) */ const uint32_t *centered_ii = s->ii + e*s->ii_lz_32 + e; - memset(s->wa, 0, s->wa_linesize * h * sizeof(*s->wa)); + memset(s->total_weight, 0, s->linesize * h * sizeof(*s->total_weight)); + memset(s->sum, 0, s->linesize * h * sizeof(*s->sum)); - for (offy = -r; offy <= r; offy++) { - for (offx = -r; offx <= r; offx++) { + for (int offy = -r; offy <= r; offy++) { + for (int offx = -r; offx <= r; offx++) { if (offx || offy) { struct thread_data td = { .src = src + offy*src_linesize + offx, @@ -457,14 +472,13 @@ static int nlmeans_plane(AVFilterContext *ctx, int w, int h, int p, int r, } weight_averages(dst, dst_linesize, src, src_linesize, - s->wa, s->wa_linesize, w, h); + s->total_weight, s->sum, s->linesize, w, h); return 0; } static int filter_frame(AVFilterLink *inlink, AVFrame *in) { - int i; AVFilterContext *ctx = inlink->dst; NLMeansContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -476,7 +490,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } av_frame_copy_props(out, in); - for (i = 0; i < s->nb_planes; i++) { + for (int i = 0; i < s->nb_planes; i++) { const int w = i ? s->chroma_w : inlink->w; const int h = i ? s->chroma_h : inlink->h; const int p = i ? s->patch_hsize_uv : s->patch_hsize; @@ -501,23 +515,26 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) 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) { - int i; NLMeansContext *s = ctx->priv; const double h = s->sigma * 10.; s->pdiff_scale = 1. / (h * h); s->max_meaningful_diff = log(255.) / s->pdiff_scale; - s->weight_lut = av_calloc(s->max_meaningful_diff, sizeof(*s->weight_lut)); + s->weight_lut = av_calloc(s->max_meaningful_diff + 1, sizeof(*s->weight_lut)); if (!s->weight_lut) return AVERROR(ENOMEM); - for (i = 0; i < s->max_meaningful_diff; i++) + for (int i = 0; i < s->max_meaningful_diff; i++) s->weight_lut[i] = exp(-i * s->pdiff_scale); CHECK_ODD_FIELD(research_size, "Luma research window"); @@ -534,7 +551,7 @@ static av_cold int init(AVFilterContext *ctx) s->patch_hsize = s->patch_size / 2; s->patch_hsize_uv = s->patch_size_uv / 2; - av_log(ctx, AV_LOG_INFO, "Research window: %dx%d / %dx%d, patch size: %dx%d / %dx%d\n", + av_log(ctx, AV_LOG_DEBUG, "Research window: %dx%d / %dx%d, patch size: %dx%d / %dx%d\n", s->research_size, s->research_size, s->research_size_uv, s->research_size_uv, s->patch_size, s->patch_size, s->patch_size_uv, s->patch_size_uv); @@ -548,7 +565,8 @@ static av_cold void uninit(AVFilterContext *ctx) NLMeansContext *s = ctx->priv; av_freep(&s->weight_lut); av_freep(&s->ii_orig); - av_freep(&s->wa); + av_freep(&s->total_weight); + av_freep(&s->sum); } static const AVFilterPad nlmeans_inputs[] = { diff --git a/libavfilter/vf_nlmeans.h b/libavfilter/vf_nlmeans.h index 0a9aab2928..43611a03bd 100644 --- a/libavfilter/vf_nlmeans.h +++ b/libavfilter/vf_nlmeans.h @@ -27,9 +27,20 @@ typedef struct NLMeansDSPContext { const uint8_t *s1, ptrdiff_t linesize1, const uint8_t *s2, ptrdiff_t linesize2, int w, int h); + void (*compute_weights_line)(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); } NLMeansDSPContext; void ff_nlmeans_init(NLMeansDSPContext *dsp); void ff_nlmeans_init_aarch64(NLMeansDSPContext *dsp); +void ff_nlmeans_init_x86(NLMeansDSPContext *dsp); #endif /* AVFILTER_NLMEANS_H */ diff --git a/libavfilter/vf_null.c b/libavfilter/vf_null.c index 33b1185ce0..fa80e2a102 100644 --- a/libavfilter/vf_null.c +++ b/libavfilter/vf_null.c @@ -43,6 +43,7 @@ static const AVFilterPad avfilter_vf_null_outputs[] = { const AVFilter ff_vf_null = { .name = "null", .description = NULL_IF_CONFIG_SMALL("Pass the source unchanged to the output."), + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_null_inputs), FILTER_OUTPUTS(avfilter_vf_null_outputs), }; diff --git a/libavfilter/vf_ocr.c b/libavfilter/vf_ocr.c index f6249e61fc..1648afa0f9 100644 --- a/libavfilter/vf_ocr.c +++ b/libavfilter/vf_ocr.c @@ -143,6 +143,7 @@ const AVFilter ff_vf_ocr = { .priv_class = &ocr_class, .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(ocr_inputs), FILTER_OUTPUTS(ocr_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_overlay_vulkan.c b/libavfilter/vf_overlay_vulkan.c index 4b49878b85..e87ee83000 100644 --- a/libavfilter/vf_overlay_vulkan.c +++ b/libavfilter/vf_overlay_vulkan.c @@ -18,18 +18,19 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "internal.h" #include "framesync.h" #define CGROUPS (int [3]){ 32, 32, 1 } typedef struct OverlayVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; int initialized; - VulkanPipeline *pl; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; + FFVulkanPipeline *pl; FFFrameSync fs; FFVkBuffer params_buf; @@ -79,24 +80,25 @@ static const char overlay_alpha[] = { static av_cold int init_filter(AVFilterContext *ctx) { int err; + FFVkSampler *sampler; OverlayVulkanContext *s = ctx->priv; - VkSampler *sampler = ff_vk_init_sampler(ctx, 1, VK_FILTER_NEAREST); + 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_NEAREST); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; - { /* Create the shader */ - const int planes = av_pix_fmt_count_planes(s->vkctx.output_format); const int ialpha = av_pix_fmt_desc_get(s->vkctx.input_format)->flags & AV_PIX_FMT_FLAG_ALPHA; - VulkanDescriptorSetBinding desc_i[3] = { + FFVulkanDescriptorSetBinding desc_i[3] = { { .name = "main_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, @@ -104,7 +106,7 @@ static av_cold int init_filter(AVFilterContext *ctx) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->main_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "overlay_img", @@ -113,7 +115,7 @@ static av_cold int init_filter(AVFilterContext *ctx) .elems = planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->overlay_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -127,7 +129,7 @@ static av_cold int init_filter(AVFilterContext *ctx) }, }; - VulkanDescriptorSetBinding desc_b = { + FFVulkanDescriptorSetBinding desc_b = { .name = "params", .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .mem_quali = "readonly", @@ -137,15 +139,15 @@ static av_cold int init_filter(AVFilterContext *ctx) .buf_content = "ivec2 o_offset[3], o_size[3];", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "overlay_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "overlay_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 3, 0)); /* set 0 */ - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( overlay_noalpha ); GLSLD( overlay_alpha ); @@ -161,11 +163,11 @@ static av_cold int init_filter(AVFilterContext *ctx) GLSLC(1, } ); GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); { /* Create and update buffer */ const AVPixFmtDescriptor *desc; @@ -178,14 +180,14 @@ static av_cold int init_filter(AVFilterContext *ctx) int32_t o_size[2*3]; } *par; - err = ff_vk_create_buf(ctx, &s->params_buf, + 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; - err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0); + err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); if (err) return err; @@ -205,18 +207,18 @@ static av_cold int init_filter(AVFilterContext *ctx) par->o_size[4] = par->o_size[0] >> desc->log2_chroma_w; par->o_size[5] = par->o_size[1] >> desc->log2_chroma_h; - err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1); + err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1); if (err) return err; s->params_desc.buffer = s->params_buf.buf; s->params_desc.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl, 1); + ff_vk_update_descriptor_set(vkctx, s->pl, 1); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -232,33 +234,39 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, int err; VkCommandBuffer cmd_buf; OverlayVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; int planes = av_pix_fmt_count_planes(s->vkctx.output_format); AVVkFrame *out = (AVVkFrame *)out_f->data[0]; AVVkFrame *main = (AVVkFrame *)main_f->data[0]; AVVkFrame *overlay = (AVVkFrame *)overlay_f->data[0]; - AVHWFramesContext *main_fc = (AVHWFramesContext*)main_f->hw_frames_ctx->data; + AVHWFramesContext *main_fc = (AVHWFramesContext*)main_f->hw_frames_ctx->data; AVHWFramesContext *overlay_fc = (AVHWFramesContext*)overlay_f->hw_frames_ctx->data; + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); + const VkFormat *main_sw_formats = av_vkfmt_from_pixfmt(main_fc->sw_format); + const VkFormat *overlay_sw_formats = av_vkfmt_from_pixfmt(overlay_fc->sw_format); + /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + 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(avctx, s->exec, &s->main_images[i].imageView, - main->img[i], - av_vkfmt_from_pixfmt(main_fc->sw_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->main_images[i].imageView, main->img[i], + main_sw_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->overlay_images[i].imageView, - overlay->img[i], - av_vkfmt_from_pixfmt(overlay_fc->sw_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->overlay_images[i].imageView, overlay->img[i], + overlay_sw_formats[i], ff_comp_identity_map)); - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->output_images[i].imageView, out->img[i], + output_formats[i], ff_comp_identity_map)); s->main_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -266,7 +274,7 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar[3] = { @@ -311,9 +319,9 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, }, }; - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, FF_ARRAY_ELEMS(bar), bar); + 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(bar), bar); main->layout[i] = bar[0].newLayout; main->access[i] = bar[0].dstAccessMask; @@ -325,24 +333,26 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, out->access[i] = bar[2].dstAccessMask; } - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, main_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, overlay_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -434,11 +444,10 @@ static void overlay_vulkan_uninit(AVFilterContext *avctx) { OverlayVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); + ff_vk_free_buf(&s->vkctx, &s->params_buf); + ff_vk_uninit(&s->vkctx); ff_framesync_uninit(&s->fs); - ff_vk_free_buf(avctx, &s->params_buf); - s->initialized = 0; } diff --git a/libavfilter/vf_owdenoise.c b/libavfilter/vf_owdenoise.c index f15baf7e08..bb99e8f33c 100644 --- a/libavfilter/vf_owdenoise.c +++ b/libavfilter/vf_owdenoise.c @@ -19,6 +19,11 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +// The code written by Michael Niedermayer in 70024b6b47b9eacfe01e8f92349ca9bf1ccd7d5a:libavfilter/vf_owdenoise.c +// can also be used under the LGPL due to: +// durandal_1707, if you do all the "todo" points from vf_owdenoise.c that are in that file since 2013 then sure i would be more than happy to relicense my part of it to LGPL +// michaelni: first relicense than work + /** * @todo try to change to int * @todo try lifting based implementation diff --git a/libavfilter/vf_paletteuse.c b/libavfilter/vf_paletteuse.c index 5f20cd75b2..5b300be5a5 100644 --- a/libavfilter/vf_paletteuse.c +++ b/libavfilter/vf_paletteuse.c @@ -811,7 +811,7 @@ static void debug_mean_error(PaletteUseContext *s, const AVFrame *in1, uint8_t *src2 = in2->data[0]; const int src1_linesize = in1->linesize[0] >> 2; const int src2_linesize = in2->linesize[0]; - const float div = in1->width * in1->height * s->use_alpha ? 4 : 3; + const float div = in1->width * in1->height * (s->use_alpha ? 4 : 3); unsigned mean_err = 0; for (y = 0; y < in1->height; y++) { diff --git a/libavfilter/vf_psnr.c b/libavfilter/vf_psnr.c index 2b980c17b2..19852eaa69 100644 --- a/libavfilter/vf_psnr.c +++ b/libavfilter/vf_psnr.c @@ -22,7 +22,7 @@ /** * @file - * Caculate the PSNR between two input videos. + * Calculate the PSNR between two input videos. */ #include "libavutil/avstring.h" @@ -466,5 +466,7 @@ const AVFilter ff_vf_psnr = { FILTER_INPUTS(psnr_inputs), FILTER_OUTPUTS(psnr_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_qp.c b/libavfilter/vf_qp.c index d942ba1579..7c9d60fe21 100644 --- a/libavfilter/vf_qp.c +++ b/libavfilter/vf_qp.c @@ -198,5 +198,6 @@ const AVFilter ff_vf_qp = { FILTER_INPUTS(qp_inputs), FILTER_OUTPUTS(qp_outputs), .priv_class = &qp_class, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_readeia608.c b/libavfilter/vf_readeia608.c index b9dc46e10e..a5a0249fb7 100644 --- a/libavfilter/vf_readeia608.c +++ b/libavfilter/vf_readeia608.c @@ -555,6 +555,8 @@ const AVFilter ff_vf_readeia608 = { FILTER_OUTPUTS(readeia608_outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), .uninit = uninit, - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, .process_command = process_command, }; diff --git a/libavfilter/vf_readvitc.c b/libavfilter/vf_readvitc.c index 370cf5d15d..d0fba234f7 100644 --- a/libavfilter/vf_readvitc.c +++ b/libavfilter/vf_readvitc.c @@ -242,6 +242,7 @@ const AVFilter ff_vf_readvitc = { .description = NULL_IF_CONFIG_SMALL("Read vertical interval timecode and write it to frame metadata."), .priv_size = sizeof(ReadVitcContext), .priv_class = &readvitc_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), FILTER_PIXFMTS_ARRAY(pixel_fmts), diff --git a/libavfilter/vf_scale_npp.c b/libavfilter/vf_scale_npp.c index 8da335154c..6ce82e5302 100644 --- a/libavfilter/vf_scale_npp.c +++ b/libavfilter/vf_scale_npp.c @@ -25,13 +25,13 @@ #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/parseutils.h" +#include "libavutil/eval.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -44,6 +44,7 @@ static const enum AVPixelFormat supported_formats[] = { AV_PIX_FMT_YUV420P, + AV_PIX_FMT_YUVA420P, AV_PIX_FMT_NV12, AV_PIX_FMT_YUV444P, }; @@ -67,12 +68,62 @@ typedef struct NPPScaleStageContext { struct { int width; int height; - } planes_in[3], planes_out[3]; + } planes_in[4], planes_out[4]; AVBufferRef *frames_ctx; AVFrame *frame; } NPPScaleStageContext; +static const char *const var_names[] = { + "in_w", "iw", + "in_h", "ih", + "out_w", "ow", + "out_h", "oh", + "a", + "sar", + "dar", + "n", + "t", + "pos", + "main_w", + "main_h", + "main_a", + "main_sar", + "main_dar", "mdar", + "main_n", + "main_t", + "main_pos", + NULL +}; + +enum var_name { + VAR_IN_W, VAR_IW, + VAR_IN_H, VAR_IH, + VAR_OUT_W, VAR_OW, + VAR_OUT_H, VAR_OH, + VAR_A, + VAR_SAR, + VAR_DAR, + VAR_N, + VAR_T, + VAR_POS, + VAR_S2R_MAIN_W, + VAR_S2R_MAIN_H, + VAR_S2R_MAIN_A, + VAR_S2R_MAIN_SAR, + VAR_S2R_MAIN_DAR, VAR_S2R_MDAR, + VAR_S2R_MAIN_N, + VAR_S2R_MAIN_T, + VAR_S2R_MAIN_POS, + VARS_NB +}; + +enum EvalMode { + EVAL_MODE_INIT, + EVAL_MODE_FRAME, + EVAL_MODE_NB +}; + typedef struct NPPScaleContext { const AVClass *class; @@ -102,35 +153,269 @@ typedef struct NPPScaleContext { int force_divisible_by; int interp_algo; + + char* size_str; + + AVExpr* w_pexpr; + AVExpr* h_pexpr; + + double var_values[VARS_NB]; + + int eval_mode; } NPPScaleContext; -static int nppscale_init(AVFilterContext *ctx) -{ - NPPScaleContext *s = ctx->priv; - int i; +const AVFilter ff_vf_scale2ref_npp; - if (!strcmp(s->format_str, "same")) { - s->format = AV_PIX_FMT_NONE; +static int config_props(AVFilterLink *outlink); + +static int check_exprs(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + unsigned vars_w[VARS_NB] = {0}, vars_h[VARS_NB] = {0}; + + if (!scale->w_pexpr && !scale->h_pexpr) + return AVERROR(EINVAL); + + if (scale->w_pexpr) + av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB); + if (scale->h_pexpr) + av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB); + + if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) { + av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr); + return AVERROR(EINVAL); + } + + if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) { + av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr); + return AVERROR(EINVAL); + } + + if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) && + (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) { + av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr); + } + + if (ctx->filter != &ff_vf_scale2ref_npp && + (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] || + vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] || + vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] || + vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] || + vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] || + vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] || + vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || + vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS])) { + av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref_npp variables are not valid in scale_npp filter.\n"); + return AVERROR(EINVAL); + } + + if (scale->eval_mode == EVAL_MODE_INIT && + (vars_w[VAR_N] || vars_h[VAR_N] || + vars_w[VAR_T] || vars_h[VAR_T] || + vars_w[VAR_POS] || vars_h[VAR_POS] || + vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] || + vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] || + vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) { + av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.\n"); + return AVERROR(EINVAL); + } + + return 0; +} + +static int nppscale_parse_expr(AVFilterContext* ctx, char* str_expr, + AVExpr** pexpr_ptr, const char* var, + const char* args) +{ + NPPScaleContext* scale = ctx->priv; + int ret, is_inited = 0; + char* old_str_expr = NULL; + AVExpr* old_pexpr = NULL; + + if (str_expr) { + old_str_expr = av_strdup(str_expr); + if (!old_str_expr) + return AVERROR(ENOMEM); + av_opt_set(scale, var, args, 0); + } + + if (*pexpr_ptr) { + old_pexpr = *pexpr_ptr; + *pexpr_ptr = NULL; + is_inited = 1; + } + + ret = av_expr_parse(pexpr_ptr, args, var_names, NULL, NULL, NULL, NULL, 0, + ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Cannot parse expression for %s: '%s'\n", var, + args); + goto revert; + } + + ret = check_exprs(ctx); + if (ret < 0) + goto revert; + + if (is_inited && (ret = config_props(ctx->outputs[0])) < 0) + goto revert; + + av_expr_free(old_pexpr); + old_pexpr = NULL; + av_freep(&old_str_expr); + + return 0; + +revert: + av_expr_free(*pexpr_ptr); + *pexpr_ptr = NULL; + if (old_str_expr) { + av_opt_set(scale, var, old_str_expr, 0); + av_free(old_str_expr); + } + if (old_pexpr) + *pexpr_ptr = old_pexpr; + + return ret; +} + +static av_cold int nppscale_init(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + int i, ret; + + if (!strcmp(scale->format_str, "same")) { + scale->format = AV_PIX_FMT_NONE; } else { - s->format = av_get_pix_fmt(s->format_str); - if (s->format == AV_PIX_FMT_NONE) { - av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str); + scale->format = av_get_pix_fmt(scale->format_str); + if (scale->format == AV_PIX_FMT_NONE) { + av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", scale->format_str); return AVERROR(EINVAL); } } - for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { - s->stages[i].frame = av_frame_alloc(); - if (!s->stages[i].frame) + if (scale->size_str && (scale->w_expr || scale->h_expr)) { + av_log(ctx, AV_LOG_ERROR, + "Size and width/height exprs cannot be set at the same time.\n"); + return AVERROR(EINVAL); + } + + if (scale->w_expr && !scale->h_expr) + FFSWAP(char*, scale->w_expr, scale->size_str); + + if (scale->size_str) { + char buf[32]; + ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str); + if (0 > ret) { + av_log(ctx, AV_LOG_ERROR, "Invalid size '%s'\n", scale->size_str); + return ret; + } + + snprintf(buf, sizeof(buf) - 1, "%d", scale->w); + ret = av_opt_set(scale, "w", buf, 0); + if (ret < 0) + return ret; + + snprintf(buf, sizeof(buf) - 1, "%d", scale->h); + ret = av_opt_set(scale, "h", buf, 0); + if (ret < 0) + return ret; + } + + if (!scale->w_expr) { + ret = av_opt_set(scale, "w", "iw", 0); + if (ret < 0) + return ret; + } + + if (!scale->h_expr) { + ret = av_opt_set(scale, "h", "ih", 0); + if (ret < 0) + return ret; + } + + ret = nppscale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr); + if (ret < 0) + return ret; + + ret = nppscale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr); + if (ret < 0) + return ret; + + for (i = 0; i < FF_ARRAY_ELEMS(scale->stages); i++) { + scale->stages[i].frame = av_frame_alloc(); + if (!scale->stages[i].frame) return AVERROR(ENOMEM); } - s->tmp_frame = av_frame_alloc(); - if (!s->tmp_frame) + scale->tmp_frame = av_frame_alloc(); + if (!scale->tmp_frame) return AVERROR(ENOMEM); return 0; } +static int nppscale_eval_dimensions(AVFilterContext* ctx) +{ + NPPScaleContext* scale = ctx->priv; + const char scale2ref = ctx->filter == &ff_vf_scale2ref_npp; + const AVFilterLink* inlink = ctx->inputs[scale2ref ? 1 : 0]; + char* expr; + int eval_w, eval_h; + int ret; + double res; + + scale->var_values[VAR_IN_W] = scale->var_values[VAR_IW] = inlink->w; + scale->var_values[VAR_IN_H] = scale->var_values[VAR_IH] = inlink->h; + scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = NAN; + scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = NAN; + scale->var_values[VAR_A] = (double)inlink->w / inlink->h; + scale->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ? + (double)inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1; + scale->var_values[VAR_DAR] = scale->var_values[VAR_A] * scale->var_values[VAR_SAR]; + + if (scale2ref) { + const AVFilterLink* main_link = ctx->inputs[0]; + + scale->var_values[VAR_S2R_MAIN_W] = main_link->w; + scale->var_values[VAR_S2R_MAIN_H] = main_link->h; + scale->var_values[VAR_S2R_MAIN_A] = (double)main_link->w / main_link->h; + scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ? + (double)main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1; + scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] = + scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR]; + } + + res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); + eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res; + + res = av_expr_eval(scale->h_pexpr, scale->var_values, NULL); + if (isnan(res)) { + expr = scale->h_expr; + ret = AVERROR(EINVAL); + goto fail; + } + eval_h = scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = (int)res == 0 ? inlink->h : (int)res; + + res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL); + if (isnan(res)) { + expr = scale->w_expr; + ret = AVERROR(EINVAL); + goto fail; + } + eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res; + + scale->w = eval_w; + scale->h = eval_h; + + return 0; + +fail: + av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'.\n", + expr); + return ret; +} + static void nppscale_uninit(AVFilterContext *ctx) { NPPScaleContext *s = ctx->priv; @@ -141,6 +426,10 @@ static void nppscale_uninit(AVFilterContext *ctx) av_buffer_unref(&s->stages[i].frames_ctx); } av_frame_free(&s->tmp_frame); + + av_expr_free(s->w_pexpr); + av_expr_free(s->h_pexpr); + s->w_pexpr = s->h_pexpr = NULL; } static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) @@ -164,6 +453,13 @@ static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) stage->planes_out[i].height = stage->planes_out[0].height >> out_sh; } + if (AV_PIX_FMT_YUVA420P == stage->in_fmt) { + stage->planes_in[3].width = stage->planes_in[0].width; + stage->planes_in[3].height = stage->planes_in[0].height; + stage->planes_out[3].width = stage->planes_out[0].width; + stage->planes_out[3].height = stage->planes_out[0].height; + } + out_ref = av_hwframe_ctx_alloc(device_ctx); if (!out_ref) return AVERROR(ENOMEM); @@ -326,31 +622,32 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig return 0; } -static int nppscale_config_props(AVFilterLink *outlink) +static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; - AVFilterLink *inlink = outlink->src->inputs[0]; + AVFilterLink *inlink0 = outlink->src->inputs[0]; + AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref_npp ? + outlink->src->inputs[1] : + outlink->src->inputs[0]; NPPScaleContext *s = ctx->priv; - int w, h; int ret; - if ((ret = ff_scale_eval_dimensions(s, - s->w_expr, s->h_expr, - inlink, outlink, - &w, &h)) < 0) + if ((ret = nppscale_eval_dimensions(ctx)) < 0) goto fail; - ff_scale_adjust_dimensions(inlink, &w, &h, - s->force_original_aspect_ratio, s->force_divisible_by); + ff_scale_adjust_dimensions(inlink, &s->w, &s->h, + s->force_original_aspect_ratio, + s->force_divisible_by); - if (((int64_t)h * inlink->w) > INT_MAX || - ((int64_t)w * inlink->h) > INT_MAX) + if (s->w > INT_MAX || s->h > INT_MAX || + (s->h * inlink->w) > INT_MAX || + (s->w * inlink->h) > INT_MAX) av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n"); - outlink->w = w; - outlink->h = h; + outlink->w = s->w; + outlink->h = s->h; - ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h); + ret = init_processing_chain(ctx, inlink0->w, inlink0->h, outlink->w, outlink->h); if (ret < 0) return ret; @@ -370,6 +667,22 @@ fail: return ret; } +static int config_props_ref(AVFilterLink *outlink) +{ + AVFilterLink *inlink = outlink->src->inputs[1]; + AVFilterContext *ctx = outlink->src; + + outlink->w = inlink->w; + outlink->h = inlink->h; + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + outlink->time_base = inlink->time_base; + outlink->frame_rate = inlink->frame_rate; + + ctx->outputs[1]->hw_frames_ctx = av_buffer_ref(ctx->inputs[1]->hw_frames_ctx); + + return 0; +} + static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage, AVFrame *out, AVFrame *in) { @@ -454,12 +767,71 @@ static int (*const nppscale_process[])(AVFilterContext *ctx, NPPScaleStageContex [STAGE_INTERLEAVE] = nppscale_interleave, }; -static int nppscale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in) +static int nppscale_scale(AVFilterLink *link, AVFrame *out, AVFrame *in) { + AVFilterContext *ctx = link->dst; NPPScaleContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; AVFrame *src = in; + char buf[32]; int i, ret, last_stage = -1; + int frame_changed; + frame_changed = in->width != link->w || + in->height != link->h || + in->format != link->format || + in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || + in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; + + if (s->eval_mode == EVAL_MODE_FRAME || frame_changed) { + unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 }; + + av_expr_count_vars(s->w_pexpr, vars_w, VARS_NB); + av_expr_count_vars(s->h_pexpr, vars_h, VARS_NB); + + if (s->eval_mode == EVAL_MODE_FRAME && !frame_changed && ctx->filter != &ff_vf_scale2ref_npp && + !(vars_w[VAR_N] || vars_w[VAR_T] || vars_w[VAR_POS]) && + !(vars_h[VAR_N] || vars_h[VAR_T] || vars_h[VAR_POS]) && + s->w && s->h) + goto scale; + + if (s->eval_mode == EVAL_MODE_INIT) { + snprintf(buf, sizeof(buf)-1, "%d", outlink->w); + av_opt_set(s, "w", buf, 0); + snprintf(buf, sizeof(buf)-1, "%d", outlink->h); + av_opt_set(s, "h", buf, 0); + + ret = nppscale_parse_expr(ctx, NULL, &s->w_pexpr, "width", s->w_expr); + if (ret < 0) + return ret; + + ret = nppscale_parse_expr(ctx, NULL, &s->h_pexpr, "height", s->h_expr); + if (ret < 0) + return ret; + } + + if (ctx->filter == &ff_vf_scale2ref_npp) { + s->var_values[VAR_S2R_MAIN_N] = link->frame_count_out; + s->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base); + s->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } else { + s->var_values[VAR_N] = link->frame_count_out; + s->var_values[VAR_T] = TS2T(in->pts, link->time_base); + s->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } + + link->format = in->format; + link->w = in->width; + link->h = in->height; + + link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; + link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; + + if ((ret = config_props(outlink)) < 0) + return ret; + } + +scale: for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) { if (!s->stages[i].stage_needed) continue; @@ -516,7 +888,7 @@ static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in) if (ret < 0) goto fail; - ret = nppscale_scale(ctx, out, in); + ret = nppscale_scale(link, out, in); CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPopCurrent(&dummy)); if (ret < 0) @@ -535,12 +907,54 @@ fail: return ret; } +static int nppscale_filter_frame_ref(AVFilterLink *link, AVFrame *in) +{ + NPPScaleContext *scale = link->dst->priv; + AVFilterLink *outlink = link->dst->outputs[1]; + int frame_changed; + + frame_changed = in->width != link->w || + in->height != link->h || + in->format != link->format || + in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || + in->sample_aspect_ratio.num != link->sample_aspect_ratio.num; + + if (frame_changed) { + link->format = in->format; + link->w = in->width; + link->h = in->height; + link->sample_aspect_ratio.num = in->sample_aspect_ratio.num; + link->sample_aspect_ratio.den = in->sample_aspect_ratio.den; + + config_props_ref(outlink); + } + + if (scale->eval_mode == EVAL_MODE_FRAME) { + scale->var_values[VAR_N] = link->frame_count_out; + scale->var_values[VAR_T] = TS2T(in->pts, link->time_base); + scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos; + } + + return ff_filter_frame(outlink, in); +} + +static int request_frame(AVFilterLink *outlink) +{ + return ff_request_frame(outlink->src->inputs[0]); +} + +static int request_frame_ref(AVFilterLink *outlink) +{ + return ff_request_frame(outlink->src->inputs[1]); +} + #define OFFSET(x) offsetof(NPPScaleContext, x) #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM) static const AVOption options[] = { - { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS }, - { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS }, + { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, + { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS }, { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS }, + { "s", "Output video size", OFFSET(size_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" }, { "nn", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN }, 0, 0, FLAGS, "interp_algo" }, @@ -551,11 +965,14 @@ static const AVOption options[] = { { "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" }, { "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" }, { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" }, - { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, "force_oar" }, + { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FLAGS, "force_oar" }, { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" }, { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" }, { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" }, - { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, + { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, FLAGS }, + { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, { .i64 = EVAL_MODE_INIT }, 0, EVAL_MODE_NB-1, FLAGS, "eval" }, + { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_INIT }, 0, 0, FLAGS, "eval" }, + { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_FRAME }, 0, 0, FLAGS, "eval" }, { NULL }, }; @@ -564,6 +981,7 @@ static const AVClass nppscale_class = { .item_name = av_default_item_name, .option = options, .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, }; static const AVFilterPad nppscale_inputs[] = { @@ -571,15 +989,15 @@ static const AVFilterPad nppscale_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .filter_frame = nppscale_filter_frame, - }, + } }; static const AVFilterPad nppscale_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .config_props = nppscale_config_props, - }, + .config_props = config_props, + } }; const AVFilter ff_vf_scale_npp = { @@ -600,3 +1018,51 @@ const AVFilter ff_vf_scale_npp = { .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; + +static const AVFilterPad nppscale2ref_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = nppscale_filter_frame, + }, + { + .name = "ref", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = nppscale_filter_frame_ref, + } +}; + +static const AVFilterPad nppscale2ref_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + .request_frame= request_frame, + }, + { + .name = "ref", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props_ref, + .request_frame= request_frame_ref, + } +}; + +const AVFilter ff_vf_scale2ref_npp = { + .name = "scale2ref_npp", + .description = NULL_IF_CONFIG_SMALL("NVIDIA Performance Primitives video " + "scaling and format conversion to the " + "given reference."), + + .init = nppscale_init, + .uninit = nppscale_uninit, + + .priv_size = sizeof(NPPScaleContext), + .priv_class = &nppscale_class, + + FILTER_INPUTS(nppscale2ref_inputs), + FILTER_OUTPUTS(nppscale2ref_outputs), + + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), + + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_scale_vulkan.c b/libavfilter/vf_scale_vulkan.c index 2b83170029..c87a8d7e2e 100644 --- a/libavfilter/vf_scale_vulkan.c +++ b/libavfilter/vf_scale_vulkan.c @@ -18,7 +18,7 @@ #include "libavutil/random_seed.h" #include "libavutil/opt.h" -#include "vulkan.h" +#include "vulkan_filter.h" #include "scale_eval.h" #include "internal.h" #include "colorspace.h" @@ -33,11 +33,11 @@ enum ScalerFunc { }; typedef struct ScaleVulkanContext { - VulkanFilterContext vkctx; + FFVulkanContext vkctx; - int initialized; + FFVkQueueFamilyCtx qf; FFVkExecContext *exec; - VulkanPipeline *pl; + FFVulkanPipeline *pl; FFVkBuffer params_buf; /* Shader updators, must be in the main filter struct */ @@ -45,11 +45,14 @@ typedef struct ScaleVulkanContext { VkDescriptorImageInfo output_images[3]; VkDescriptorBufferInfo params_desc; - enum ScalerFunc scaler; char *out_format_string; - enum AVColorRange out_range; char *w_expr; char *h_expr; + + enum ScalerFunc scaler; + enum AVColorRange out_range; + + int initialized; } ScaleVulkanContext; static const char scale_bilinear[] = { @@ -107,18 +110,18 @@ static const char write_444[] = { static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) { int err; - VkSampler *sampler; + FFVkSampler *sampler; VkFilter sampler_mode; ScaleVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; int crop_x = in->crop_left; int crop_y = in->crop_top; int crop_w = in->width - (in->crop_left + in->crop_right); int crop_h = in->height - (in->crop_top + in->crop_bottom); + int in_planes = av_pix_fmt_count_planes(s->vkctx.input_format); - s->vkctx.queue_family_idx = s->vkctx.hwctx->queue_family_comp_index; - s->vkctx.queue_count = GET_QUEUE_COUNT(s->vkctx.hwctx, 0, 1, 0); - s->vkctx.cur_queue_idx = av_get_random_seed() % s->vkctx.queue_count; + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); switch (s->scaler) { case F_NEAREST: @@ -130,24 +133,24 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }; /* Create a sampler */ - sampler = ff_vk_init_sampler(ctx, 0, sampler_mode); + sampler = ff_vk_init_sampler(vkctx, 0, sampler_mode); if (!sampler) return AVERROR_EXTERNAL; - s->pl = ff_vk_create_pipeline(ctx); + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); if (!s->pl) return AVERROR(ENOMEM); { /* Create the shader */ - VulkanDescriptorSetBinding desc_i[2] = { + FFVulkanDescriptorSetBinding desc_i[2] = { { .name = "input_img", .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .dimensions = 2, - .elems = av_pix_fmt_count_planes(s->vkctx.input_format), + .elems = in_planes, .stages = VK_SHADER_STAGE_COMPUTE_BIT, .updater = s->input_images, - .samplers = DUP_SAMPLER_ARRAY4(*sampler), + .sampler = sampler, }, { .name = "output_img", @@ -161,7 +164,7 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) }, }; - VulkanDescriptorSetBinding desc_b = { + FFVulkanDescriptorSetBinding desc_b = { .name = "params", .type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, .mem_quali = "readonly", @@ -171,15 +174,15 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) .buf_content = "mat4 yuv_matrix;", }; - SPIRVShader *shd = ff_vk_init_shader(ctx, s->pl, "scale_compute", - VK_SHADER_STAGE_COMPUTE_BIT); + FFVkSPIRVShader *shd = ff_vk_init_shader(s->pl, "scale_compute", + VK_SHADER_STAGE_COMPUTE_BIT); if (!shd) return AVERROR(ENOMEM); - ff_vk_set_compute_shader_sizes(ctx, shd, CGROUPS); + ff_vk_set_compute_shader_sizes(shd, CGROUPS); - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, desc_i, 2, 0)); /* set 0 */ - RET(ff_vk_add_descriptor_set(ctx, s->pl, shd, &desc_b, 1, 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, desc_i, FF_ARRAY_ELEMS(desc_i), 0)); /* set 0 */ + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, &desc_b, 1, 0)); /* set 1 */ GLSLD( scale_bilinear ); @@ -229,11 +232,11 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) GLSLC(0, } ); - RET(ff_vk_compile_shader(ctx, shd, "main")); + RET(ff_vk_compile_shader(vkctx, shd, "main")); } - RET(ff_vk_init_pipeline_layout(ctx, s->pl)); - RET(ff_vk_init_compute_pipeline(ctx, s->pl)); + RET(ff_vk_init_pipeline_layout(vkctx, s->pl)); + RET(ff_vk_init_compute_pipeline(vkctx, s->pl)); if (s->vkctx.output_format != s->vkctx.input_format) { const struct LumaCoefficients *lcoeffs; @@ -249,14 +252,14 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) return AVERROR(EINVAL); } - err = ff_vk_create_buf(ctx, &s->params_buf, + 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; - err = ff_vk_map_buffers(ctx, &s->params_buf, (uint8_t **)&par, 1, 0); + err = ff_vk_map_buffers(vkctx, &s->params_buf, (uint8_t **)&par, 1, 0); if (err) return err; @@ -270,18 +273,18 @@ static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) par->yuv_matrix[3][3] = 1.0; - err = ff_vk_unmap_buffers(ctx, &s->params_buf, 1, 1); + err = ff_vk_unmap_buffers(vkctx, &s->params_buf, 1, 1); if (err) return err; s->params_desc.buffer = s->params_buf.buf; s->params_desc.range = VK_WHOLE_SIZE; - ff_vk_update_descriptor_set(ctx, s->pl, 1); + ff_vk_update_descriptor_set(vkctx, s->pl, 1); } /* Execution context */ - RET(ff_vk_create_exec_ctx(ctx, &s->exec)); + RET(ff_vk_create_exec_ctx(vkctx, &s->exec, &s->qf)); s->initialized = 1; @@ -296,36 +299,38 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) int err = 0; VkCommandBuffer cmd_buf; ScaleVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + FFVulkanFunctions *vk = &vkctx->vkfn; AVVkFrame *in = (AVVkFrame *)in_f->data[0]; AVVkFrame *out = (AVVkFrame *)out_f->data[0]; VkImageMemoryBarrier barriers[AV_NUM_DATA_POINTERS*2]; int barrier_count = 0; + const int planes = av_pix_fmt_count_planes(s->vkctx.input_format); + const VkFormat *input_formats = av_vkfmt_from_pixfmt(s->vkctx.input_format); + const VkFormat *output_formats = av_vkfmt_from_pixfmt(s->vkctx.output_format); /* Update descriptors and init the exec context */ - ff_vk_start_exec_recording(avctx, s->exec); - cmd_buf = ff_vk_get_exec_buf(avctx, s->exec); + ff_vk_start_exec_recording(vkctx, s->exec); + cmd_buf = ff_vk_get_exec_buf(s->exec); - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->input_images[i].imageView, - in->img[i], - av_vkfmt_from_pixfmt(s->vkctx.input_format)[i], + for (int i = 0; i < planes; i++) { + RET(ff_vk_create_imageview(vkctx, s->exec, + &s->input_images[i].imageView, in->img[i], + input_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->input_images[i].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - } - - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.output_format); i++) { - RET(ff_vk_create_imageview(avctx, s->exec, &s->output_images[i].imageView, - out->img[i], - av_vkfmt_from_pixfmt(s->vkctx.output_format)[i], - ff_comp_identity_map)); - s->output_images[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL; } - ff_vk_update_descriptor_set(avctx, s->pl, 0); + ff_vk_update_descriptor_set(vkctx, s->pl, 0); - for (int i = 0; i < av_pix_fmt_count_planes(s->vkctx.input_format); i++) { + for (int i = 0; i < planes; i++) { VkImageMemoryBarrier bar = { .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, .srcAccessMask = 0, @@ -367,27 +372,29 @@ static int process_frames(AVFilterContext *avctx, AVFrame *out_f, AVFrame *in_f) out->access[i] = bar.dstAccessMask; } - vkCmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, - 0, NULL, 0, NULL, barrier_count, barriers); + vk->CmdPipelineBarrier(cmd_buf, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, + 0, NULL, 0, NULL, barrier_count, barriers); - ff_vk_bind_pipeline_exec(avctx, s->exec, s->pl); + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); - vkCmdDispatch(cmd_buf, - FFALIGN(s->vkctx.output_width, CGROUPS[0])/CGROUPS[0], - FFALIGN(s->vkctx.output_height, CGROUPS[1])/CGROUPS[1], 1); + vk->CmdDispatch(cmd_buf, + FFALIGN(vkctx->output_width, CGROUPS[0])/CGROUPS[0], + FFALIGN(vkctx->output_height, CGROUPS[1])/CGROUPS[1], 1); - ff_vk_add_exec_dep(avctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - ff_vk_add_exec_dep(avctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, in_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, out_f, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); - err = ff_vk_submit_exec_queue(avctx, s->exec); + err = ff_vk_submit_exec_queue(vkctx, s->exec); if (err) return err; + ff_vk_qf_rotate(&s->qf); + return err; fail: - ff_vk_discard_exec_deps(avctx, s->exec); + ff_vk_discard_exec_deps(s->exec); return err; } @@ -433,11 +440,12 @@ static int scale_vulkan_config_output(AVFilterLink *outlink) int err; AVFilterContext *avctx = outlink->src; ScaleVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; AVFilterLink *inlink = outlink->src->inputs[0]; err = ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink, - &s->vkctx.output_width, - &s->vkctx.output_height); + &vkctx->output_width, + &vkctx->output_height); if (err < 0) return err; @@ -478,8 +486,8 @@ static void scale_vulkan_uninit(AVFilterContext *avctx) { ScaleVulkanContext *s = avctx->priv; - ff_vk_filter_uninit(avctx); - ff_vk_free_buf(avctx, &s->params_buf); + ff_vk_free_buf(&s->vkctx, &s->params_buf); + ff_vk_uninit(&s->vkctx); s->initialized = 0; } diff --git a/libavfilter/vf_scdet.c b/libavfilter/vf_scdet.c index d11d2e2e2c..1576759c24 100644 --- a/libavfilter/vf_scdet.c +++ b/libavfilter/vf_scdet.c @@ -206,6 +206,7 @@ const AVFilter ff_vf_scdet = { .priv_size = sizeof(SCDetContext), .priv_class = &scdet_class, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(scdet_inputs), FILTER_OUTPUTS(scdet_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), diff --git a/libavfilter/vf_selectivecolor.c b/libavfilter/vf_selectivecolor.c index 9ace3ce4a6..ea4b5dfee2 100644 --- a/libavfilter/vf_selectivecolor.c +++ b/libavfilter/vf_selectivecolor.c @@ -223,7 +223,7 @@ static int parse_psfile(AVFilterContext *ctx, const char *fname) int k; for (k = 0; k < FF_ARRAY_ELEMS(s->cmyk_adjust[0]); k++) { READ16(val); - s->cmyk_adjust[i][k] = val / 100.; + s->cmyk_adjust[i][k] = val / 100.f; } ret = register_range(s, i); if (ret < 0) @@ -299,11 +299,11 @@ static const enum AVPixelFormat pix_fmts[] = { static inline int comp_adjust(int scale, float value, float adjust, float k, int correction_method) { const float min = -value; - const float max = 1. - value; - float res = (-1. - adjust) * k - adjust; + const float max = 1.f - value; + float res = (-1.f - adjust) * k - adjust; if (correction_method == CORRECTION_METHOD_RELATIVE) res *= max; - return lrint(av_clipf(res, min, max) * scale); + return lrintf(av_clipf(res, min, max) * scale); } #define DECLARE_SELECTIVE_COLOR_FUNC(nbits) \ diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c index 0a79599bab..b3893adc13 100644 --- a/libavfilter/vf_setparams.c +++ b/libavfilter/vf_setparams.c @@ -165,6 +165,7 @@ const AVFilter ff_vf_setparams = { .description = NULL_IF_CONFIG_SMALL("Force field, or color property for the output video frame."), .priv_size = sizeof(SetParamsContext), .priv_class = &setparams_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; @@ -204,6 +205,7 @@ const AVFilter ff_vf_setrange = { .priv_size = sizeof(SetParamsContext), .init = init_setrange, .priv_class = &setrange_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; @@ -238,6 +240,7 @@ const AVFilter ff_vf_setfield = { .priv_size = sizeof(SetParamsContext), .init = init_setfield, .priv_class = &setfield_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(inputs), FILTER_OUTPUTS(outputs), }; diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index c8c7b986b5..71728bced4 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -27,6 +27,7 @@ #include "libavutil/bswap.h" #include "libavutil/adler32.h" #include "libavutil/display.h" +#include "libavutil/dovi_meta.h" #include "libavutil/imgutils.h" #include "libavutil/internal.h" #include "libavutil/film_grain_params.h" @@ -221,7 +222,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) av_log(ctx, AV_LOG_INFO, "num_windows: %d, ", hdr_plus->num_windows); for (int w = 1; w < hdr_plus->num_windows; w++) { AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; - av_log(ctx, AV_LOG_INFO, "window %d { ", w); + av_log(ctx, AV_LOG_INFO, w > 1 ? ", window %d { " : "window %d { ", w); av_log(ctx, AV_LOG_INFO, "window_upper_left_corner: (%5.4f,%5.4f),", av_q2d(params->window_upper_left_corner_x), av_q2d(params->window_upper_left_corner_y)); @@ -242,7 +243,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) params->semimajor_axis_external_ellipse); av_log(ctx, AV_LOG_INFO, "semiminor_axis_external_ellipse: %d, ", params->semiminor_axis_external_ellipse); - av_log(ctx, AV_LOG_INFO, "overlap_process_option: %d}, ", + av_log(ctx, AV_LOG_INFO, "overlap_process_option: %d}", params->overlap_process_option); } av_log(ctx, AV_LOG_INFO, "targeted_system_display_maximum_luminance: %9.4f, ", @@ -252,7 +253,7 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) for (int i = 0; i < hdr_plus->num_rows_targeted_system_display_actual_peak_luminance; i++) { av_log(ctx, AV_LOG_INFO, "("); for (int j = 0; j < hdr_plus->num_cols_targeted_system_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->targeted_system_display_actual_peak_luminance[i][j])); } av_log(ctx, AV_LOG_INFO, ")"); @@ -264,9 +265,9 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) AVHDRPlusColorTransformParams *params = &hdr_plus->params[w]; av_log(ctx, AV_LOG_INFO, "window %d {maxscl: {", w); for (int i = 0; i < 3; i++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,",av_q2d(params->maxscl[i])); + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f",av_q2d(params->maxscl[i])); } - av_log(ctx, AV_LOG_INFO, "} average_maxrgb: %5.4f, ", + av_log(ctx, AV_LOG_INFO, "}, average_maxrgb: %5.4f, ", av_q2d(params->average_maxrgb)); av_log(ctx, AV_LOG_INFO, "distribution_maxrgb: {"); for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) { @@ -274,35 +275,35 @@ static void dump_dynamic_hdr_plus(AVFilterContext *ctx, AVFrameSideData *sd) params->distribution_maxrgb[i].percentage, av_q2d(params->distribution_maxrgb[i].percentile)); } - av_log(ctx, AV_LOG_INFO, "} fraction_bright_pixels: %5.4f, ", + av_log(ctx, AV_LOG_INFO, "}, fraction_bright_pixels: %5.4f", av_q2d(params->fraction_bright_pixels)); if (params->tone_mapping_flag) { - av_log(ctx, AV_LOG_INFO, "knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); + av_log(ctx, AV_LOG_INFO, ", knee_point: (%5.4f,%5.4f), ", av_q2d(params->knee_point_x), av_q2d(params->knee_point_y)); av_log(ctx, AV_LOG_INFO, "bezier_curve_anchors: {"); for (int i = 0; i < params->num_bezier_curve_anchors; i++) { - av_log(ctx, AV_LOG_INFO, "%5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(params->bezier_curve_anchors[i])); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } if (params->color_saturation_mapping_flag) { - av_log(ctx, AV_LOG_INFO, "color_saturation_weight: %5.4f", + av_log(ctx, AV_LOG_INFO, ", color_saturation_weight: %5.4f", av_q2d(params->color_saturation_weight)); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } if (hdr_plus->mastering_display_actual_peak_luminance_flag) { - av_log(ctx, AV_LOG_INFO, "mastering_display_actual_peak_luminance: {"); + av_log(ctx, AV_LOG_INFO, ", mastering_display_actual_peak_luminance: {"); for (int i = 0; i < hdr_plus->num_rows_mastering_display_actual_peak_luminance; i++) { av_log(ctx, AV_LOG_INFO, "("); for (int j = 0; j < hdr_plus->num_cols_mastering_display_actual_peak_luminance; j++) { - av_log(ctx, AV_LOG_INFO, " %5.4f,", + av_log(ctx, AV_LOG_INFO, i ? ",%5.4f" : "%5.4f", av_q2d(hdr_plus->mastering_display_actual_peak_luminance[i][j])); } av_log(ctx, AV_LOG_INFO, ")"); } - av_log(ctx, AV_LOG_INFO, "} "); + av_log(ctx, AV_LOG_INFO, "}"); } } @@ -429,6 +430,110 @@ static void dump_sei_film_grain_params_metadata(AVFilterContext *ctx, const AVFr } } +static void dump_dovi_metadata(AVFilterContext *ctx, const AVFrameSideData *sd) +{ + const AVDOVIMetadata *dovi = (AVDOVIMetadata *) sd->data; + const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi); + const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi); + const AVDOVIColorMetadata *color = av_dovi_get_color(dovi); + + av_log(ctx, AV_LOG_INFO, "Dolby Vision Metadata:\n"); + av_log(ctx, AV_LOG_INFO, " rpu_type=%"PRIu8"; ", hdr->rpu_type); + av_log(ctx, AV_LOG_INFO, "rpu_format=%"PRIu16"; ", hdr->rpu_format); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_profile=%"PRIu8"; ", hdr->vdr_rpu_profile); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_level=%"PRIu8"; ", hdr->vdr_rpu_level); + av_log(ctx, AV_LOG_INFO, "chroma_resampling_explicit_filter_flag=%"PRIu8"; ", hdr->chroma_resampling_explicit_filter_flag); + av_log(ctx, AV_LOG_INFO, "coef_data_type=%"PRIu8"; ", hdr->coef_data_type); + av_log(ctx, AV_LOG_INFO, "coef_log2_denom=%"PRIu8"; ", hdr->coef_log2_denom); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_normalized_idc=%"PRIu8"; ", hdr->vdr_rpu_normalized_idc); + av_log(ctx, AV_LOG_INFO, "bl_video_full_range_flag=%"PRIu8"; ", hdr->bl_video_full_range_flag); + av_log(ctx, AV_LOG_INFO, "bl_bit_depth=%"PRIu8"; ", hdr->bl_bit_depth); + av_log(ctx, AV_LOG_INFO, "el_bit_depth=%"PRIu8"; ", hdr->el_bit_depth); + av_log(ctx, AV_LOG_INFO, "vdr_bit_depth=%"PRIu8"; ", hdr->vdr_bit_depth); + av_log(ctx, AV_LOG_INFO, "spatial_resampling_filter_flag=%"PRIu8"; ", hdr->spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "el_spatial_resampling_filter_flag=%"PRIu8"; ", hdr->el_spatial_resampling_filter_flag); + av_log(ctx, AV_LOG_INFO, "disable_residual_flag=%"PRIu8"\n", hdr->disable_residual_flag); + + av_log(ctx, AV_LOG_INFO, " data mapping: "); + av_log(ctx, AV_LOG_INFO, "vdr_rpu_id=%"PRIu8"; ", mapping->vdr_rpu_id); + av_log(ctx, AV_LOG_INFO, "mapping_color_space=%"PRIu8"; ", mapping->mapping_color_space); + av_log(ctx, AV_LOG_INFO, "mapping_chroma_format_idc=%"PRIu8"; ", mapping->mapping_chroma_format_idc); + av_log(ctx, AV_LOG_INFO, "nlq_method_idc=%d; ", (int) mapping->nlq_method_idc); + av_log(ctx, AV_LOG_INFO, "num_x_partitions=%"PRIu32"; ", mapping->num_x_partitions); + av_log(ctx, AV_LOG_INFO, "num_y_partitions=%"PRIu32"\n", mapping->num_y_partitions); + + for (int c = 0; c < 3; c++) { + const AVDOVIReshapingCurve *curve = &mapping->curves[c]; + const AVDOVINLQParams *nlq = &mapping->nlq[c]; + av_log(ctx, AV_LOG_INFO, " channel %d: ", c); + av_log(ctx, AV_LOG_INFO, "pivots={ "); + for (int i = 0; i < curve->num_pivots; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu16" ", curve->pivots[i]); + av_log(ctx, AV_LOG_INFO, "}; mapping_idc={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%d ", (int) curve->mapping_idc[i]); + av_log(ctx, AV_LOG_INFO, "}; poly_order={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->poly_order[i]); + av_log(ctx, AV_LOG_INFO, "}; poly_coef={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) { + av_log(ctx, AV_LOG_INFO, "{%"PRIi64", %"PRIi64", %"PRIi64"} ", + curve->poly_coef[i][0], + curve->poly_coef[i][1], + curve->poly_coef[i][2]); + } + + av_log(ctx, AV_LOG_INFO, "}; mmr_order={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIu8" ", curve->mmr_order[i]); + av_log(ctx, AV_LOG_INFO, "}; mmr_constant={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) + av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_constant[i]); + av_log(ctx, AV_LOG_INFO, "}; mmr_coef={ "); + for (int i = 0; i < curve->num_pivots - 1; i++) { + av_log(ctx, AV_LOG_INFO, "{"); + for (int j = 0; j < curve->mmr_order[i]; j++) { + for (int k = 0; k < 7; k++) + av_log(ctx, AV_LOG_INFO, "%"PRIi64" ", curve->mmr_coef[i][j][k]); + } + av_log(ctx, AV_LOG_INFO, "} "); + } + + av_log(ctx, AV_LOG_INFO, "}; nlq_offset=%"PRIu16"; ", nlq->nlq_offset); + av_log(ctx, AV_LOG_INFO, "vdr_in_max=%"PRIu64"; ", nlq->vdr_in_max); + switch (mapping->nlq_method_idc) { + case AV_DOVI_NLQ_LINEAR_DZ: + av_log(ctx, AV_LOG_INFO, "linear_deadzone_slope=%"PRIu64"; ", nlq->linear_deadzone_slope); + av_log(ctx, AV_LOG_INFO, "linear_deadzone_threshold=%"PRIu64"\n", nlq->linear_deadzone_threshold); + break; + } + } + + av_log(ctx, AV_LOG_INFO, " color metadata: "); + av_log(ctx, AV_LOG_INFO, "dm_metadata_id=%"PRIu8"; ", color->dm_metadata_id); + av_log(ctx, AV_LOG_INFO, "scene_refresh_flag=%"PRIu8"; ", color->scene_refresh_flag); + av_log(ctx, AV_LOG_INFO, "ycc_to_rgb_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; ycc_to_rgb_offset={ "); + for (int i = 0; i < 3; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->ycc_to_rgb_offset[i])); + av_log(ctx, AV_LOG_INFO, "}; rgb_to_lms_matrix={ "); + for (int i = 0; i < 9; i++) + av_log(ctx, AV_LOG_INFO, "%f ", av_q2d(color->rgb_to_lms_matrix[i])); + av_log(ctx, AV_LOG_INFO, "}; signal_eotf=%"PRIu16"; ", color->signal_eotf); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param0=%"PRIu16"; ", color->signal_eotf_param0); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param1=%"PRIu16"; ", color->signal_eotf_param1); + av_log(ctx, AV_LOG_INFO, "signal_eotf_param2=%"PRIu32"; ", color->signal_eotf_param2); + av_log(ctx, AV_LOG_INFO, "signal_bit_depth=%"PRIu8"; ", color->signal_bit_depth); + av_log(ctx, AV_LOG_INFO, "signal_color_space=%"PRIu8"; ", color->signal_color_space); + av_log(ctx, AV_LOG_INFO, "signal_chroma_format=%"PRIu8"; ", color->signal_chroma_format); + av_log(ctx, AV_LOG_INFO, "signal_full_range_flag=%"PRIu8"; ", color->signal_full_range_flag); + av_log(ctx, AV_LOG_INFO, "source_min_pq=%"PRIu16"; ", color->source_min_pq); + av_log(ctx, AV_LOG_INFO, "source_max_pq=%"PRIu16"; ", color->source_max_pq); + av_log(ctx, AV_LOG_INFO, "source_diagonal=%"PRIu16"; ", color->source_diagonal); +} + static void dump_color_property(AVFilterContext *ctx, AVFrame *frame) { const char *color_range_str = av_color_range_name(frame->color_range); @@ -617,6 +722,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame) case AV_FRAME_DATA_FILM_GRAIN_PARAMS: dump_sei_film_grain_params_metadata(ctx, sd); break; + case AV_FRAME_DATA_DOVI_METADATA: + dump_dovi_metadata(ctx, sd); + break; default: av_log(ctx, AV_LOG_WARNING, "unknown side data type %d " "(%"SIZE_SPECIFIER" bytes)\n", sd->type, sd->size); @@ -678,4 +786,5 @@ const AVFilter ff_vf_showinfo = { FILTER_OUTPUTS(avfilter_vf_showinfo_outputs), .priv_size = sizeof(ShowInfoContext), .priv_class = &showinfo_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_ssim.c b/libavfilter/vf_ssim.c index af1d161e21..32f313817d 100644 --- a/libavfilter/vf_ssim.c +++ b/libavfilter/vf_ssim.c @@ -31,7 +31,7 @@ /* * @file - * Caculate the SSIM between two input videos. + * Calculate the SSIM between two input videos. */ #include "libavutil/avstring.h" @@ -592,5 +592,7 @@ const AVFilter ff_vf_ssim = { FILTER_INPUTS(ssim_inputs), FILTER_OUTPUTS(ssim_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c index 377160c72b..3fc4eeb63d 100644 --- a/libavfilter/vf_subtitles.c +++ b/libavfilter/vf_subtitles.c @@ -147,8 +147,8 @@ static int config_input(AVFilterLink *inlink) ass_set_frame_size (ass->renderer, inlink->w, inlink->h); if (ass->original_w && ass->original_h) - ass_set_aspect_ratio(ass->renderer, (double)inlink->w / inlink->h, - (double)ass->original_w / ass->original_h); + ass_set_pixel_aspect(ass->renderer, (double)inlink->w / inlink->h / + ((double)ass->original_w / ass->original_h)); if (ass->shaping != -1) ass_set_shaper(ass->renderer, ass->shaping); diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c index 363df8034b..1285dbaa4d 100644 --- a/libavfilter/vf_tonemap.c +++ b/libavfilter/vf_tonemap.c @@ -119,18 +119,19 @@ static float mobius(float in, float j, double peak) static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, const AVPixFmtDescriptor *desc, int x, int y, double peak) { - const float *r_in = (const float *)(in->data[0] + x * desc->comp[0].step + y * in->linesize[0]); - const float *b_in = (const float *)(in->data[1] + x * desc->comp[1].step + y * in->linesize[1]); - const float *g_in = (const float *)(in->data[2] + x * desc->comp[2].step + y * in->linesize[2]); - float *r_out = (float *)(out->data[0] + x * desc->comp[0].step + y * out->linesize[0]); - float *b_out = (float *)(out->data[1] + x * desc->comp[1].step + y * out->linesize[1]); - float *g_out = (float *)(out->data[2] + x * desc->comp[2].step + y * out->linesize[2]); + int map[3] = { desc->comp[0].plane, desc->comp[1].plane, desc->comp[2].plane }; + const float *r_in = (const float *)(in->data[map[0]] + x * desc->comp[map[0]].step + y * in->linesize[map[0]]); + const float *g_in = (const float *)(in->data[map[1]] + x * desc->comp[map[1]].step + y * in->linesize[map[1]]); + const float *b_in = (const float *)(in->data[map[2]] + x * desc->comp[map[2]].step + y * in->linesize[map[2]]); + float *r_out = (float *)(out->data[map[0]] + x * desc->comp[map[0]].step + y * out->linesize[map[0]]); + float *g_out = (float *)(out->data[map[1]] + x * desc->comp[map[1]].step + y * out->linesize[map[1]]); + float *b_out = (float *)(out->data[map[2]] + x * desc->comp[map[2]].step + y * out->linesize[map[2]]); float sig, sig_orig; /* load values */ *r_out = *r_in; - *b_out = *b_in; *g_out = *g_in; + *b_out = *b_in; /* desaturate to prevent unnatural colors */ if (s->desat > 0) { diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index f9f0d70cd5..b964daeee3 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -328,6 +328,7 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, static int filter_frame(AVFilterLink *inlink, AVFrame *in) { + int err = 0; AVFilterContext *ctx = inlink->dst; TransContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; @@ -339,10 +340,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) { - av_frame_free(&in); - return AVERROR(ENOMEM); + err = AVERROR(ENOMEM); + goto fail; } - av_frame_copy_props(out, in); + + err = av_frame_copy_props(out, in); + if (err < 0) + goto fail; if (in->sample_aspect_ratio.num == 0) { out->sample_aspect_ratio = in->sample_aspect_ratio; @@ -356,6 +360,11 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); av_frame_free(&in); return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; } #define OFFSET(x) offsetof(TransContext, x) diff --git a/libavfilter/vf_transpose_vulkan.c b/libavfilter/vf_transpose_vulkan.c new file mode 100644 index 0000000000..30d052e08c --- /dev/null +++ b/libavfilter/vf_transpose_vulkan.c @@ -0,0 +1,346 @@ +/* + * copyright (c) 2021 Wu Jianhua + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "transpose.h" + +#define CGS 32 + +typedef struct TransposeVulkanContext { + FFVulkanContext vkctx; + FFVkQueueFamilyCtx qf; + FFVkExecContext *exec; + FFVulkanPipeline *pl; + + VkDescriptorImageInfo input_images[3]; + VkDescriptorImageInfo output_images[3]; + + int dir; + int passthrough; + int initialized; +} TransposeVulkanContext; + +static av_cold int init_filter(AVFilterContext *ctx, AVFrame *in) +{ + int err = 0; + FFVkSPIRVShader *shd; + TransposeVulkanContext *s = ctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + 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, + .updater = s->input_images, + }, + { + .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, + }, + }; + + image_descs[0].sampler = ff_vk_init_sampler(vkctx, 1, VK_FILTER_LINEAR); + if (!image_descs[0].sampler) + return AVERROR_EXTERNAL; + + ff_vk_qf_init(vkctx, &s->qf, VK_QUEUE_COMPUTE_BIT, 0); + + { + s->pl = ff_vk_create_pipeline(vkctx, &s->qf); + if (!s->pl) + return AVERROR(ENOMEM); + + shd = ff_vk_init_shader(s->pl, "transpose_compute", image_descs[0].stages); + if (!shd) + return AVERROR(ENOMEM); + + ff_vk_set_compute_shader_sizes(shd, (int [3]){ CGS, 1, 1 }); + RET(ff_vk_add_descriptor_set(vkctx, s->pl, shd, image_descs, FF_ARRAY_ELEMS(image_descs), 0)); + + GLSLC(0, void main() ); + GLSLC(0, { ); + GLSLC(1, ivec2 size; ); + GLSLC(1, 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->dir == TRANSPOSE_CCLOCK) + GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.y - pos.y, pos.x)); ,i); + else if (s->dir == TRANSPOSE_CLOCK_FLIP || s->dir == TRANSPOSE_CLOCK) { + GLSLF(2, vec4 res = texture(input_images[%i], ivec2(size.yx - pos.yx)); ,i); + if (s->dir == TRANSPOSE_CLOCK) + GLSLC(2, pos = ivec2(pos.x, size.y - pos.y); ); + } else + GLSLF(2, vec4 res = texture(input_images[%i], pos.yx); ,i); + GLSLF(2, imageStore(output_images[%i], pos, res); ,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 *outframe, AVFrame *inframe) +{ + int err = 0; + VkCommandBuffer cmd_buf; + TransposeVulkanContext *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 *in = (AVVkFrame *)inframe->data[0]; + AVVkFrame *out = (AVVkFrame *)outframe->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(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->input_images[i].imageView, in->img[i], + input_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->input_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 = in->layout[i], + .newLayout = s->input_images[i].imageLayout, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = in->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); + + in->layout[i] = barriers[0].newLayout; + in->access[i] = barriers[0].dstAccessMask; + + out->layout[i] = barriers[1].newLayout; + out->access[i] = barriers[1].dstAccessMask; + } + + ff_vk_bind_pipeline_exec(vkctx, s->exec, s->pl); + vk->CmdDispatch(cmd_buf, FFALIGN(s->vkctx.output_width, CGS)/CGS, + s->vkctx.output_height, 1); + + ff_vk_add_exec_dep(vkctx, s->exec, inframe, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT); + ff_vk_add_exec_dep(vkctx, s->exec, outframe, 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 filter_frame(AVFilterLink *inlink, AVFrame *in) +{ + int err; + AVFrame *out = NULL; + AVFilterContext *ctx = inlink->dst; + TransposeVulkanContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + + if (s->passthrough) + return ff_filter_frame(outlink, in); + + out = ff_get_video_buffer(outlink, outlink->w, outlink->h); + if (!out) { + err = AVERROR(ENOMEM); + goto fail; + } + + if (!s->initialized) + RET(init_filter(ctx, in)); + + RET(process_frames(ctx, out, in)); + + RET(av_frame_copy_props(out, in)); + + if (in->sample_aspect_ratio.num) + out->sample_aspect_ratio = in->sample_aspect_ratio; + else { + out->sample_aspect_ratio.num = in->sample_aspect_ratio.den; + out->sample_aspect_ratio.den = in->sample_aspect_ratio.num; + } + + av_frame_free(&in); + + return ff_filter_frame(outlink, out); + +fail: + av_frame_free(&in); + av_frame_free(&out); + return err; +} + +static av_cold void transpose_vulkan_uninit(AVFilterContext *avctx) +{ + TransposeVulkanContext *s = avctx->priv; + ff_vk_uninit(&s->vkctx); + + s->initialized = 0; +} + +static int config_props_output(AVFilterLink *outlink) +{ + AVFilterContext *avctx = outlink->src; + TransposeVulkanContext *s = avctx->priv; + FFVulkanContext *vkctx = &s->vkctx; + AVFilterLink *inlink = avctx->inputs[0]; + + if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || + (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { + av_log(avctx, AV_LOG_VERBOSE, + "w:%d h:%d -> w:%d h:%d (passthrough mode)\n", + inlink->w, inlink->h, inlink->w, inlink->h); + outlink->hw_frames_ctx = av_buffer_ref(inlink->hw_frames_ctx); + return outlink->hw_frames_ctx ? 0 : AVERROR(ENOMEM); + } else { + s->passthrough = TRANSPOSE_PT_TYPE_NONE; + } + + vkctx->output_width = inlink->h; + vkctx->output_height = inlink->w; + + if (inlink->sample_aspect_ratio.num) + outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 }, + inlink->sample_aspect_ratio); + else + outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; + + return ff_vk_filter_config_output(outlink); +} + +#define OFFSET(x) offsetof(TransposeVulkanContext, x) +#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM) + +static const AVOption transpose_vulkan_options[] = { + { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, "dir" }, + { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, + { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" }, + { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" }, + { "clock_flip", "rotate clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, + + { "passthrough", "do not apply transposition if the input matches the specified geometry", + OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE}, 0, INT_MAX, FLAGS, "passthrough" }, + { "none", "always apply transposition", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + { "portrait", "preserve portrait geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + { "landscape", "preserve landscape geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, "passthrough" }, + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(transpose_vulkan); + +static const AVFilterPad transpose_vulkan_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = &filter_frame, + .config_props = &ff_vk_filter_config_input, + } +}; + +static const AVFilterPad transpose_vulkan_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = &config_props_output, + } +}; + +const AVFilter ff_vf_transpose_vulkan = { + .name = "transpose_vulkan", + .description = NULL_IF_CONFIG_SMALL("Transpose Vulkan Filter"), + .priv_size = sizeof(TransposeVulkanContext), + .init = &ff_vk_filter_init, + .uninit = &transpose_vulkan_uninit, + FILTER_INPUTS(transpose_vulkan_inputs), + FILTER_OUTPUTS(transpose_vulkan_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VULKAN), + .priv_class = &transpose_vulkan_class, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_v360.c b/libavfilter/vf_v360.c index ed25e1f07d..9e590a228c 100644 --- a/libavfilter/vf_v360.c +++ b/libavfilter/vf_v360.c @@ -163,8 +163,10 @@ static const AVOption v360_options[] = { { "ih_fov", "input horizontal field of view",OFFSET(ih_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "ih_fov"}, { "iv_fov", "input vertical field of view", OFFSET(iv_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "iv_fov"}, { "id_fov", "input diagonal field of view", OFFSET(id_fov), AV_OPT_TYPE_FLOAT, {.dbl=0.f}, 0.f, 360.f,TFLAGS, "id_fov"}, + { "h_offset", "output horizontal off-axis offset",OFFSET(h_offset), AV_OPT_TYPE_FLOAT,{.dbl=0.f}, -1.f, 1.f,TFLAGS, "h_offset"}, + { "v_offset", "output vertical off-axis offset", OFFSET(v_offset), AV_OPT_TYPE_FLOAT,{.dbl=0.f}, -1.f, 1.f,TFLAGS, "v_offset"}, {"alpha_mask", "build mask in alpha plane", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS, "alpha"}, - { "reset_rot", "reset rotation", OFFSET(reset_rot), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1,TFLAGS, "reset_rot"}, + { "reset_rot", "reset rotation", OFFSET(reset_rot), AV_OPT_TYPE_BOOL, {.i64=0}, -1, 1,TFLAGS, "reset_rot"}, { NULL } }; @@ -1027,6 +1029,17 @@ static inline void rotate_cube_face_inverse(float *uf, float *vf, int rotation) } } +/** + * Offset vector. + * + * @param vec vector + */ +static void offset_vector(float *vec, float h_offset, float v_offset) +{ + vec[0] += h_offset; + vec[1] += v_offset; +} + /** * Normalize vector. * @@ -1103,8 +1116,6 @@ static void cube_to_xyz(const V360Context *s, vec[0] = l_x; vec[1] = l_y; vec[2] = l_z; - - normalize_vector(vec); } /** @@ -1854,8 +1865,6 @@ static int stereographic_to_xyz(const V360Context *s, vec[1] = y / r * sin_theta; vec[2] = cosf(theta); - normalize_vector(vec); - return 1; } @@ -1960,8 +1969,6 @@ static int equisolid_to_xyz(const V360Context *s, vec[1] = y / r * sin_theta; vec[2] = cosf(theta); - normalize_vector(vec); - return 1; } @@ -2066,12 +2073,11 @@ static int orthographic_to_xyz(const V360Context *s, vec[0] = x; vec[1] = y; - normalize_vector(vec); return 1; } else { - vec[0] = 0; - vec[1] = 0; - vec[2] = 1; + vec[0] = 0.f; + vec[1] = 0.f; + vec[2] = 1.f; return 0; } @@ -2474,8 +2480,6 @@ static int hammer_to_xyz(const V360Context *s, vec[1] = M_SQRT2 * y * z; vec[2] = w * (bb - aa) / (aa + bb); - normalize_vector(vec); - return 1; } @@ -2546,8 +2550,6 @@ static int sinusoidal_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -2743,8 +2745,6 @@ static int eac_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -2846,8 +2846,6 @@ static int flat_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = 1.f; - normalize_vector(vec); - return 1; } @@ -2897,8 +2895,6 @@ static int fisheye_to_xyz(const V360Context *s, vec[1] = cos_theta * sin_phi; vec[2] = sin_theta; - normalize_vector(vec); - return 1; } @@ -2993,8 +2989,6 @@ static int pannini_to_xyz(const V360Context *s, vec[1] = sinf(lat); vec[2] = cosf(lon) * cosf(lat); - normalize_vector(vec); - return 1; } @@ -3090,8 +3084,6 @@ static int cylindrical_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -3217,8 +3209,6 @@ static int cylindricalea_to_xyz(const V360Context *s, vec[1] = sin_theta; vec[2] = cos_theta * cos_phi; - normalize_vector(vec); - return 1; } @@ -3331,8 +3321,6 @@ static int tetrahedron_to_xyz(const V360Context *s, vec[1] = 1.f - vf * 2.f; vec[2] = 2.f * fabsf(1.f - fabsf(1.f - uf * 2.f + vf)) - 1.f; - normalize_vector(vec); - return 1; } @@ -3444,8 +3432,6 @@ static int dfisheye_to_xyz(const V360Context *s, vec[1] = cos_theta * vf / lh; vec[2] = sin_theta; - normalize_vector(vec); - return 1; } @@ -3568,8 +3554,6 @@ static int barrel_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -3826,8 +3810,6 @@ static int barrelsplit_to_xyz(const V360Context *s, vec[1] = l_y; vec[2] = l_z; - normalize_vector(vec); - return 1; } @@ -3884,8 +3866,6 @@ static int tspyramid_to_xyz(const V360Context *s, vec[2] = -2.f * (1.f - y) / 0.375f + 1.f; } - normalize_vector(vec); - return 1; } @@ -3987,8 +3967,6 @@ static int octahedron_to_xyz(const V360Context *s, vec[1] = y; } - normalize_vector(vec); - return 1; } @@ -4254,9 +4232,9 @@ static void fov_from_dfov(int format, float d_fov, float w, float h, float *h_fo static void set_dimensions(int *outw, int *outh, int w, int h, const AVPixFmtDescriptor *desc) { - outw[1] = outw[2] = FF_CEIL_RSHIFT(w, desc->log2_chroma_w); + outw[1] = outw[2] = AV_CEIL_RSHIFT(w, desc->log2_chroma_w); outw[0] = outw[3] = w; - outh[1] = outh[2] = FF_CEIL_RSHIFT(h, desc->log2_chroma_h); + outh[1] = outh[2] = AV_CEIL_RSHIFT(h, desc->log2_chroma_h); outh[0] = outh[3] = h; } @@ -4293,6 +4271,8 @@ static av_always_inline int v360_slice(AVFilterContext *ctx, void *arg, int jobn out_mask = s->out_transform(s, j, i, height, width, vec); else out_mask = s->out_transform(s, i, j, width, height, vec); + offset_vector(vec, s->h_offset, s->v_offset); + normalize_vector(vec); av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2])); rotate(s->rot_quaternion, vec); av_assert1(!isnan(vec[0]) && !isnan(vec[1]) && !isnan(vec[2])); @@ -4961,8 +4941,10 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar V360Context *s = ctx->priv; int ret; - s->yaw = s->pitch = s->roll = 0.f; - s->reset_rot = 0; + if (s->reset_rot <= 0) + s->yaw = s->pitch = s->roll = 0.f; + if (s->reset_rot < 0) + s->reset_rot = 0; ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags); if (ret < 0) diff --git a/libavfilter/vf_vfrdet.c b/libavfilter/vf_vfrdet.c index fda8c2d485..0ca221b5b8 100644 --- a/libavfilter/vf_vfrdet.c +++ b/libavfilter/vf_vfrdet.c @@ -108,6 +108,7 @@ const AVFilter ff_vf_vfrdet = { .priv_size = sizeof(VFRDETContext), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(vfrdet_inputs), FILTER_OUTPUTS(vfrdet_outputs), }; diff --git a/libavfilter/vf_vidstabdetect.c b/libavfilter/vf_vidstabdetect.c index 05c95d0eeb..267a62ea9b 100644 --- a/libavfilter/vf_vidstabdetect.c +++ b/libavfilter/vf_vidstabdetect.c @@ -196,6 +196,7 @@ const AVFilter ff_vf_vidstabdetect = { .priv_size = sizeof(StabData), .init = init, .uninit = uninit, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(avfilter_vf_vidstabdetect_inputs), FILTER_OUTPUTS(avfilter_vf_vidstabdetect_outputs), FILTER_PIXFMTS_ARRAY(ff_vidstab_pix_fmts), diff --git a/libavfilter/vf_vif.c b/libavfilter/vf_vif.c index 09854641b1..818cc51e36 100644 --- a/libavfilter/vf_vif.c +++ b/libavfilter/vf_vif.c @@ -638,5 +638,7 @@ const AVFilter ff_vf_vif = { FILTER_INPUTS(vif_inputs), FILTER_OUTPUTS(vif_outputs), FILTER_PIXFMTS_ARRAY(pix_fmts), - .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | AVFILTER_FLAG_SLICE_THREADS, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL | + AVFILTER_FLAG_SLICE_THREADS | + AVFILTER_FLAG_METADATA_ONLY, }; diff --git a/libavfilter/vf_vmafmotion.c b/libavfilter/vf_vmafmotion.c index 362839735e..8b7e9b17ef 100644 --- a/libavfilter/vf_vmafmotion.c +++ b/libavfilter/vf_vmafmotion.c @@ -363,6 +363,7 @@ const AVFilter ff_vf_vmafmotion = { .uninit = uninit, .priv_size = sizeof(VMAFMotionContext), .priv_class = &vmafmotion_class, + .flags = AVFILTER_FLAG_METADATA_ONLY, FILTER_INPUTS(vmafmotion_inputs), FILTER_OUTPUTS(vmafmotion_outputs), FILTER_QUERY_FUNC(query_formats), diff --git a/libavfilter/vf_vpp_qsv.c b/libavfilter/vf_vpp_qsv.c index ab58a5777e..5c96703fd3 100644 --- a/libavfilter/vf_vpp_qsv.c +++ b/libavfilter/vf_vpp_qsv.c @@ -26,6 +26,7 @@ #include "libavutil/opt.h" #include "libavutil/eval.h" #include "libavutil/hwcontext.h" +#include "libavutil/hwcontext_qsv.h" #include "libavutil/pixdesc.h" #include "libavutil/mathematics.h" @@ -139,8 +140,9 @@ 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 } }; @@ -297,6 +299,32 @@ static int config_input(AVFilterLink *inlink) return 0; } +static mfxStatus get_mfx_version(const AVFilterContext *ctx, mfxVersion *mfx_version) +{ + const AVFilterLink *inlink = ctx->inputs[0]; + AVBufferRef *device_ref; + AVHWDeviceContext *device_ctx; + AVQSVDeviceContext *device_hwctx; + + if (inlink->hw_frames_ctx) { + AVHWFramesContext *frames_ctx = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + device_ref = frames_ctx->device_ref; + } else if (ctx->hw_device_ctx) { + device_ref = ctx->hw_device_ctx; + } else { + // Unavailable hw context doesn't matter in pass-through mode, + // so don't error here but let runtime version checks fail by setting to 0.0 + mfx_version->Major = 0; + mfx_version->Minor = 0; + return MFX_ERR_NONE; + } + + device_ctx = (AVHWDeviceContext *)device_ref->data; + device_hwctx = device_ctx->hwctx; + + return MFXQueryVersion(device_hwctx->session, mfx_version); +} + static int config_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -304,6 +332,7 @@ static int config_output(AVFilterLink *outlink) QSVVPPParam param = { NULL }; QSVVPPCrop crop = { 0 }; mfxExtBuffer *ext_buf[ENH_FILTERS_COUNT]; + mfxVersion mfx_version; AVFilterLink *inlink = ctx->inputs[0]; enum AVPixelFormat in_format; @@ -317,6 +346,11 @@ static int config_output(AVFilterLink *outlink) param.ext_buf = ext_buf; param.async_depth = vpp->async_depth; + if (get_mfx_version(ctx, &mfx_version) != MFX_ERR_NONE) { + av_log(ctx, AV_LOG_ERROR, "Failed to query mfx version.\n"); + return AVERROR(EINVAL); + } + if (inlink->format == AV_PIX_FMT_QSV) { if (!inlink->hw_frames_ctx || !inlink->hw_frames_ctx->data) return AVERROR(EINVAL); @@ -467,19 +501,20 @@ static int config_output(AVFilterLink *outlink) #endif } - if (inlink->w != outlink->w || inlink->h != outlink->h) { #ifdef QSV_HAVE_SCALING_CONFIG - memset(&vpp->scale_conf, 0, sizeof(mfxExtVPPScaling)); - vpp->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; - vpp->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); - vpp->scale_conf.ScalingMode = vpp->scale_mode; + 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)); + vpp->scale_conf.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; + vpp->scale_conf.Header.BufferSz = sizeof(mfxExtVPPScaling); + vpp->scale_conf.ScalingMode = vpp->scale_mode; - param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf; -#else - av_log(ctx, AV_LOG_WARNING, "The QSV VPP Scale option is " - "not supported with this MSDK version.\n"); -#endif + param.ext_buf[param.num_ext_buf++] = (mfxExtBuffer*)&vpp->scale_conf; + } else + 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 || diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c index da1ab5a8ff..685b8a2035 100644 --- a/libavfilter/vf_yadif_cuda.c +++ b/libavfilter/vf_yadif_cuda.c @@ -212,23 +212,6 @@ static av_cold void deint_cuda_uninit(AVFilterContext *ctx) s->input_frames = NULL; } -static int deint_cuda_query_formats(AVFilterContext *ctx) -{ - enum AVPixelFormat pix_fmts[] = { - AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, - }; - int ret; - - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->inputs[0]->outcfg.formats)) < 0) - return ret; - if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), - &ctx->outputs[0]->incfg.formats)) < 0) - return ret; - - return 0; -} - static int config_input(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; @@ -380,9 +363,9 @@ const AVFilter ff_vf_yadif_cuda = { .priv_size = sizeof(DeintCUDAContext), .priv_class = &yadif_cuda_class, .uninit = deint_cuda_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA), FILTER_INPUTS(deint_cuda_inputs), FILTER_OUTPUTS(deint_cuda_outputs), - FILTER_QUERY_FUNC(deint_cuda_query_formats), .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, }; diff --git a/libavfilter/vf_yadif_videotoolbox.m b/libavfilter/vf_yadif_videotoolbox.m new file mode 100644 index 0000000000..455745817f --- /dev/null +++ b/libavfilter/vf_yadif_videotoolbox.m @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2018 Philip Langdale + * 2020 Aman Karmani + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "internal.h" +#include "metal/utils.h" +#include "yadif.h" +#include "libavutil/avassert.h" +#include "libavutil/hwcontext.h" +#include "libavutil/objc.h" + +#include + +extern char ff_vf_yadif_videotoolbox_metallib_data[]; +extern unsigned int ff_vf_yadif_videotoolbox_metallib_len; + +typedef struct API_AVAILABLE(macos(10.11), ios(8.0)) YADIFVTContext { + YADIFContext yadif; + + AVBufferRef *device_ref; + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + id mtlDevice; + id mtlLibrary; + id mtlQueue; + id mtlPipeline; + id mtlFunction; + id mtlParamsBuffer; + + CVMetalTextureCacheRef textureCache; +} YADIFVTContext API_AVAILABLE(macos(10.11), ios(8.0)); + +// Using sizeof(YADIFVTContext) outside of an availability check will error +// if we're targeting an older OS version, so we need to calculate the size ourselves +// (we'll statically verify it's correct in yadif_videotoolbox_init behind a check) +#define YADIF_VT_CTX_SIZE (sizeof(YADIFContext) + sizeof(void*) * 10) + +struct mtlYadifParams { + uint channels; + uint parity; + uint tff; + bool is_second_field; + bool skip_spatial_check; + int field_mode; +}; + +static void call_kernel(AVFilterContext *ctx, + id dst, + id prev, + id cur, + id next, + int channels, + int parity, + int tff) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + YADIFVTContext *s = ctx->priv; + id buffer = s->mtlQueue.commandBuffer; + id encoder = buffer.computeCommandEncoder; + struct mtlYadifParams *params = (struct mtlYadifParams *)s->mtlParamsBuffer.contents; + *params = (struct mtlYadifParams){ + .channels = channels, + .parity = parity, + .tff = tff, + .is_second_field = !(parity ^ tff), + .skip_spatial_check = s->yadif.mode&2, + .field_mode = s->yadif.current_field + }; + + [encoder setTexture:dst atIndex:0]; + [encoder setTexture:prev atIndex:1]; + [encoder setTexture:cur atIndex:2]; + [encoder setTexture:next atIndex:3]; + [encoder setBuffer:s->mtlParamsBuffer offset:0 atIndex:4]; + ff_metal_compute_encoder_dispatch(s->mtlDevice, s->mtlPipeline, encoder, dst.width, dst.height); + [encoder endEncoding]; + + [buffer commit]; + [buffer waitUntilCompleted]; + + ff_objc_release(&encoder); + ff_objc_release(&buffer); +} + +static void filter(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int i; + + for (i = 0; i < y->csp->nb_components; i++) { + int pixel_size, channels; + const AVComponentDescriptor *comp = &y->csp->comp[i]; + CVMetalTextureRef prev, cur, next, dest; + id tex_prev, tex_cur, tex_next, tex_dest; + MTLPixelFormat format; + + if (comp->plane < i) { + // We process planes as a whole, so don't reprocess + // them for additional components + continue; + } + + pixel_size = (comp->depth + comp->shift) / 8; + channels = comp->step / pixel_size; + if (pixel_size > 2 || channels > 2) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + switch (pixel_size) { + case 1: + format = channels == 1 ? MTLPixelFormatR8Unorm : MTLPixelFormatRG8Unorm; + break; + case 2: + format = channels == 1 ? MTLPixelFormatR16Unorm : MTLPixelFormatRG16Unorm; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + av_log(ctx, AV_LOG_TRACE, + "Deinterlacing plane %d: pixel_size: %d channels: %d\n", + comp->plane, pixel_size, channels); + + prev = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->prev->data[3], i, format); + cur = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->cur->data[3], i, format); + next = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)y->next->data[3], i, format); + dest = ff_metal_texture_from_pixbuf(ctx, s->textureCache, (CVPixelBufferRef)dst->data[3], i, format); + + tex_prev = CVMetalTextureGetTexture(prev); + tex_cur = CVMetalTextureGetTexture(cur); + tex_next = CVMetalTextureGetTexture(next); + tex_dest = CVMetalTextureGetTexture(dest); + + call_kernel(ctx, tex_dest, tex_prev, tex_cur, tex_next, + channels, parity, tff); + + CFRelease(prev); + CFRelease(cur); + CFRelease(next); + CFRelease(dest); + } + + CVBufferPropagateAttachments((CVPixelBufferRef)y->cur->data[3], (CVPixelBufferRef)dst->data[3]); + + if (y->current_field == YADIF_FIELD_END) { + y->current_field = YADIF_FIELD_NORMAL; + } + +exit: + return; +} + +static av_cold void do_uninit(AVFilterContext *ctx) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + + av_frame_free(&y->prev); + av_frame_free(&y->cur); + av_frame_free(&y->next); + + av_buffer_unref(&s->device_ref); + av_buffer_unref(&s->input_frames_ref); + s->input_frames = NULL; + + ff_objc_release(&s->mtlParamsBuffer); + ff_objc_release(&s->mtlFunction); + ff_objc_release(&s->mtlPipeline); + ff_objc_release(&s->mtlQueue); + ff_objc_release(&s->mtlLibrary); + ff_objc_release(&s->mtlDevice); + + if (s->textureCache) { + CFRelease(s->textureCache); + s->textureCache = NULL; + } +} + + +static av_cold void yadif_videotoolbox_uninit(AVFilterContext *ctx) +{ + if (@available(macOS 10.11, iOS 8.0, *)) { + do_uninit(ctx); + } +} + +static av_cold int do_init(AVFilterContext *ctx) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + YADIFVTContext *s = ctx->priv; + NSError *err = nil; + CVReturn ret; + + s->mtlDevice = MTLCreateSystemDefaultDevice(); + if (!s->mtlDevice) { + av_log(ctx, AV_LOG_ERROR, "Unable to find Metal device\n"); + goto fail; + } + + av_log(ctx, AV_LOG_INFO, "Using Metal device: %s\n", s->mtlDevice.name.UTF8String); + + dispatch_data_t libData = dispatch_data_create( + ff_vf_yadif_videotoolbox_metallib_data, + ff_vf_yadif_videotoolbox_metallib_len, + nil, + nil); + s->mtlLibrary = [s->mtlDevice newLibraryWithData:libData error:&err]; + dispatch_release(libData); + libData = nil; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to load Metal library: %s\n", err.description.UTF8String); + goto fail; + } + + s->mtlFunction = [s->mtlLibrary newFunctionWithName:@"deint"]; + if (!s->mtlFunction) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal function!\n"); + goto fail; + } + + s->mtlQueue = s->mtlDevice.newCommandQueue; + if (!s->mtlQueue) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal command queue!\n"); + goto fail; + } + + s->mtlPipeline = [s->mtlDevice + newComputePipelineStateWithFunction:s->mtlFunction + error:&err]; + if (err) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal compute pipeline: %s\n", err.description.UTF8String); + goto fail; + } + + s->mtlParamsBuffer = [s->mtlDevice + newBufferWithLength:sizeof(struct mtlYadifParams) + options:MTLResourceStorageModeShared]; + if (!s->mtlParamsBuffer) { + av_log(ctx, AV_LOG_ERROR, "Failed to create Metal buffer for parameters\n"); + goto fail; + } + + ret = CVMetalTextureCacheCreate( + NULL, + NULL, + s->mtlDevice, + NULL, + &s->textureCache + ); + if (ret != kCVReturnSuccess) { + av_log(ctx, AV_LOG_ERROR, "Failed to create CVMetalTextureCache: %d\n", ret); + goto fail; + } + + return 0; +fail: + yadif_videotoolbox_uninit(ctx); + return AVERROR_EXTERNAL; +} + +static av_cold int yadif_videotoolbox_init(AVFilterContext *ctx) +{ + if (@available(macOS 10.11, iOS 8.0, *)) { + // Ensure we calculated YADIF_VT_CTX_SIZE correctly + static_assert(YADIF_VT_CTX_SIZE == sizeof(YADIFVTContext), "Incorrect YADIF_VT_CTX_SIZE value!"); + return do_init(ctx); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + +static int do_config_input(AVFilterLink *inlink) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + AVFilterContext *ctx = inlink->dst; + YADIFVTContext *s = ctx->priv; + + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!s->input_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + s->input_frames = (AVHWFramesContext*)s->input_frames_ref->data; + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + if (@available(macOS 10.11, iOS 8.0, *)) { + return do_config_input(inlink); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + +static int do_config_output(AVFilterLink *link) API_AVAILABLE(macos(10.11), ios(8.0)) +{ + AVHWFramesContext *output_frames; + AVFilterContext *ctx = link->src; + YADIFVTContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int ret = 0; + + av_assert0(s->input_frames); + s->device_ref = av_buffer_ref(s->input_frames->device_ref); + if (!s->device_ref) { + av_log(ctx, AV_LOG_ERROR, "A device reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + + link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); + if (!link->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); + goto exit; + } + + output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; + output_frames->sw_format = s->input_frames->sw_format; + output_frames->width = ctx->inputs[0]->w; + output_frames->height = ctx->inputs[0]->h; + + ret = ff_filter_init_hw_frames(ctx, link, 10); + if (ret < 0) + goto exit; + + ret = av_hwframe_ctx_init(link->hw_frames_ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise VideoToolbox frame " + "context for output: %d\n", ret); + goto exit; + } + + link->time_base.num = ctx->inputs[0]->time_base.num; + link->time_base.den = ctx->inputs[0]->time_base.den * 2; + link->w = ctx->inputs[0]->w; + link->h = ctx->inputs[0]->h; + + if(y->mode & 1) + link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); + + if (link->w < 3 || link->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); + ret = AVERROR(EINVAL); + goto exit; + } + + y->csp = av_pix_fmt_desc_get(output_frames->sw_format); + y->filter = filter; + +exit: + return ret; +} + +static int config_output(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + if (@available(macOS 10.11, iOS 8.0, *)) { + return do_config_output(link); + } else { + av_log(ctx, AV_LOG_ERROR, "Metal is not available on this OS version\n"); + return AVERROR(ENOSYS); + } +} + +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } + +static const AVOption yadif_videotoolbox_options[] = { + #define OFFSET(x) offsetof(YADIFContext, x) + { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"}, + CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"), + CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"), + CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"), + CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"), + + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=YADIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"), + CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"), + CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"), + + { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=YADIF_DEINT_ALL}, 0, 1, FLAGS, "deint" }, + CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"), + CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"), + #undef OFFSET + + { NULL } +}; + +AVFILTER_DEFINE_CLASS(yadif_videotoolbox); + +static const AVFilterPad yadif_videotoolbox_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = config_input, + }, +}; + +static const AVFilterPad yadif_videotoolbox_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = config_output, + }, +}; + +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, + .priv_class = &yadif_videotoolbox_class, + .init = yadif_videotoolbox_init, + .uninit = yadif_videotoolbox_uninit, + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX), + FILTER_INPUTS(yadif_videotoolbox_inputs), + FILTER_OUTPUTS(yadif_videotoolbox_outputs), + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c index 3f7dba489a..1288c5efc1 100644 --- a/libavfilter/vf_zscale.c +++ b/libavfilter/vf_zscale.c @@ -554,6 +554,24 @@ fail: return ret; } +static void update_output_color_information(ZScaleContext *s, AVFrame *frame) +{ + if (s->colorspace != -1) + frame->colorspace = (int)s->dst_format.matrix_coefficients; + + if (s->primaries != -1) + frame->color_primaries = (int)s->dst_format.color_primaries; + + if (s->range != -1) + frame->color_range = convert_range_from_zimg(s->dst_format.pixel_range); + + if (s->trc != -1) + frame->color_trc = (int)s->dst_format.transfer_characteristics; + + if (s->chromal != -1) + frame->chroma_location = (int)s->dst_format.chroma_location + 1; +} + static int filter_frame(AVFilterLink *link, AVFrame *in) { ZScaleContext *s = link->dst->priv; @@ -621,20 +639,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) format_init(&s->dst_format, out, odesc, s->colorspace, s->primaries, s->trc, s->range, s->chromal); - if (s->colorspace != -1) - out->colorspace = (int)s->dst_format.matrix_coefficients; - - if (s->primaries != -1) - out->color_primaries = (int)s->dst_format.color_primaries; - - if (s->range != -1) - out->color_range = convert_range_from_zimg(s->dst_format.pixel_range); - - if (s->trc != -1) - out->color_trc = (int)s->dst_format.transfer_characteristics; - - if (s->chromal != -1) - out->chroma_location = (int)s->dst_format.chroma_location - 1; + update_output_color_information(s, out); ret = graph_build(&s->graph, &s->params, &s->src_format, &s->dst_format, &s->tmp, &s->tmp_size); @@ -680,17 +685,7 @@ static int filter_frame(AVFilterLink *link, AVFrame *in) } } - if (s->colorspace != -1) - out->colorspace = (int)s->dst_format.matrix_coefficients; - - if (s->primaries != -1) - out->color_primaries = (int)s->dst_format.color_primaries; - - if (s->range != -1) - out->color_range = convert_range_from_zimg(s->dst_format.pixel_range); - - if (s->trc != -1) - out->color_trc = (int)s->dst_format.transfer_characteristics; + 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, diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index 6f48a8f86c..20b915d472 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -70,6 +70,9 @@ typedef struct TestSourceContext { /* only used by testsrc2 */ int alpha; + /* only used by colorspectrum */ + int type; + /* only used by color */ FFDrawContext draw; FFDrawColor color; @@ -1791,3 +1794,92 @@ const AVFilter ff_vsrc_allrgb = { }; #endif /* CONFIG_ALLRGB_FILTER */ + +#if CONFIG_COLORSPECTRUM_FILTER + +static const AVOption colorspectrum_options[] = { + COMMON_OPTIONS + { "type", "set the color spectrum type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" }, + { "black","fade to black", 0, AV_OPT_TYPE_CONST,{.i64=0},0, 0, FLAGS, "type" }, + { "white","fade to white", 0, AV_OPT_TYPE_CONST,{.i64=1},0, 0, FLAGS, "type" }, + { "all", "white to black", 0, AV_OPT_TYPE_CONST,{.i64=2},0, 0, FLAGS, "type" }, + { NULL } +}; + +AVFILTER_DEFINE_CLASS(colorspectrum); + +static inline float mix(float a, float b, float mix) +{ + return a * mix + b * (1.f - mix); +} + +static void hsb2rgb(const float *c, float *rgb) +{ + rgb[0] = av_clipf(fabsf(fmodf(c[0] * 6.f + 0.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[1] = av_clipf(fabsf(fmodf(c[0] * 6.f + 4.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[2] = av_clipf(fabsf(fmodf(c[0] * 6.f + 2.f, 6.f) - 3.f) - 1.f, 0.f, 1.f); + rgb[0] = mix(c[3], (rgb[0] * rgb[0] * (3.f - 2.f * rgb[0])), c[1]) * c[2]; + rgb[1] = mix(c[3], (rgb[1] * rgb[1] * (3.f - 2.f * rgb[1])), c[1]) * c[2]; + rgb[2] = mix(c[3], (rgb[2] * rgb[2] * (3.f - 2.f * rgb[2])), c[1]) * c[2]; +} + +static void colorspectrum_fill_picture(AVFilterContext *ctx, AVFrame *frame) +{ + TestSourceContext *test = ctx->priv; + const float w = frame->width - 1.f; + const float h = frame->height - 1.f; + float c[4]; + + for (int y = 0; y < frame->height; y++) { + float *r = (float *)(frame->data[2] + y * frame->linesize[2]); + float *g = (float *)(frame->data[0] + y * frame->linesize[0]); + float *b = (float *)(frame->data[1] + y * frame->linesize[1]); + const float yh = y / h; + + c[1] = test->type == 2 ? yh > 0.5f ? 2.f * (yh - 0.5f) : 1.f - 2.f * yh : test->type == 1 ? 1.f - yh : yh; + c[2] = 1.f; + c[3] = test->type == 1 ? 1.f : test->type == 2 ? (yh > 0.5f ? 0.f : 1.f): 0.f; + for (int x = 0; x < frame->width; x++) { + float rgb[3]; + + c[0] = x / w; + hsb2rgb(c, rgb); + + r[x] = rgb[0]; + g[x] = rgb[1]; + b[x] = rgb[2]; + } + } +} + +static av_cold int colorspectrum_init(AVFilterContext *ctx) +{ + TestSourceContext *test = ctx->priv; + + test->draw_once = 1; + test->fill_picture_fn = colorspectrum_fill_picture; + return init(ctx); +} + +static const AVFilterPad avfilter_vsrc_colorspectrum_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_props, + }, +}; + +const AVFilter ff_vsrc_colorspectrum = { + .name = "colorspectrum", + .description = NULL_IF_CONFIG_SMALL("Generate colors spectrum."), + .priv_size = sizeof(TestSourceContext), + .priv_class = &colorspectrum_class, + .init = colorspectrum_init, + .uninit = uninit, + .activate = activate, + .inputs = NULL, + FILTER_OUTPUTS(avfilter_vsrc_colorspectrum_outputs), + FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRPF32), +}; + +#endif /* CONFIG_COLORSPECTRUM_FILTER */ diff --git a/libavfilter/vulkan.c b/libavfilter/vulkan.c index e812a3e723..fc8a1fa47b 100644 --- a/libavfilter/vulkan.c +++ b/libavfilter/vulkan.c @@ -16,1413 +16,4 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "formats.h" -#include "vulkan.h" -#include "glslang.h" - -/* Generic macro for creating contexts which need to keep their addresses - * if another context is created. */ -#define FN_CREATING(ctx, type, shortname, array, num) \ -static av_always_inline type *create_ ##shortname(ctx *dctx) \ -{ \ - type **array, *sctx = av_mallocz(sizeof(*sctx)); \ - if (!sctx) \ - return NULL; \ - \ - array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\ - if (!array) { \ - av_free(sctx); \ - return NULL; \ - } \ - \ - dctx->array = array; \ - dctx->array[dctx->num++] = sctx; \ - \ - return sctx; \ -} - -const VkComponentMapping ff_comp_identity_map = { - .r = VK_COMPONENT_SWIZZLE_IDENTITY, - .g = VK_COMPONENT_SWIZZLE_IDENTITY, - .b = VK_COMPONENT_SWIZZLE_IDENTITY, - .a = VK_COMPONENT_SWIZZLE_IDENTITY, -}; - -/* Converts return values to strings */ -const char *ff_vk_ret2str(VkResult res) -{ -#define CASE(VAL) case VAL: return #VAL - switch (res) { - CASE(VK_SUCCESS); - CASE(VK_NOT_READY); - CASE(VK_TIMEOUT); - CASE(VK_EVENT_SET); - CASE(VK_EVENT_RESET); - CASE(VK_INCOMPLETE); - CASE(VK_ERROR_OUT_OF_HOST_MEMORY); - CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY); - CASE(VK_ERROR_INITIALIZATION_FAILED); - CASE(VK_ERROR_DEVICE_LOST); - CASE(VK_ERROR_MEMORY_MAP_FAILED); - CASE(VK_ERROR_LAYER_NOT_PRESENT); - CASE(VK_ERROR_EXTENSION_NOT_PRESENT); - CASE(VK_ERROR_FEATURE_NOT_PRESENT); - CASE(VK_ERROR_INCOMPATIBLE_DRIVER); - CASE(VK_ERROR_TOO_MANY_OBJECTS); - CASE(VK_ERROR_FORMAT_NOT_SUPPORTED); - CASE(VK_ERROR_FRAGMENTED_POOL); - CASE(VK_ERROR_SURFACE_LOST_KHR); - CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); - CASE(VK_SUBOPTIMAL_KHR); - CASE(VK_ERROR_OUT_OF_DATE_KHR); - CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); - CASE(VK_ERROR_VALIDATION_FAILED_EXT); - CASE(VK_ERROR_INVALID_SHADER_NV); - CASE(VK_ERROR_OUT_OF_POOL_MEMORY); - CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE); - CASE(VK_ERROR_NOT_PERMITTED_EXT); - default: return "Unknown error"; - } -#undef CASE -} - -static int vk_alloc_mem(AVFilterContext *avctx, VkMemoryRequirements *req, - VkMemoryPropertyFlagBits req_flags, void *alloc_extension, - VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) -{ - VkResult ret; - int index = -1; - VkPhysicalDeviceProperties props; - VkPhysicalDeviceMemoryProperties mprops; - VulkanFilterContext *s = avctx->priv; - - VkMemoryAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, - .pNext = alloc_extension, - }; - - vkGetPhysicalDeviceProperties(s->hwctx->phys_dev, &props); - vkGetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &mprops); - - /* Align if we need to */ - if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) - req->size = FFALIGN(req->size, props.limits.minMemoryMapAlignment); - - alloc_info.allocationSize = req->size; - - /* The vulkan spec requires memory types to be sorted in the "optimal" - * order, so the first matching type we find will be the best/fastest one */ - for (int i = 0; i < mprops.memoryTypeCount; i++) { - /* The memory type must be supported by the requirements (bitfield) */ - if (!(req->memoryTypeBits & (1 << i))) - continue; - - /* The memory type flags must include our properties */ - if ((mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) - continue; - - /* Found a suitable memory type */ - index = i; - break; - } - - if (index < 0) { - av_log(avctx, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", - req_flags); - return AVERROR(EINVAL); - } - - alloc_info.memoryTypeIndex = index; - - ret = vkAllocateMemory(s->hwctx->act_dev, &alloc_info, - s->hwctx->alloc, mem); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR(ENOMEM); - } - - *mem_flags |= mprops.memoryTypes[index].propertyFlags; - - return 0; -} - -int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, - VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) -{ - int err; - VkResult ret; - int use_ded_mem; - VulkanFilterContext *s = avctx->priv; - - VkBufferCreateInfo buf_spawn = { - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = NULL, - .usage = usage, - .sharingMode = VK_SHARING_MODE_EXCLUSIVE, - .size = size, /* Gets FFALIGNED during alloc if host visible - but should be ok */ - }; - - VkBufferMemoryRequirementsInfo2 req_desc = { - .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, - }; - VkMemoryDedicatedAllocateInfo ded_alloc = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, - .pNext = NULL, - }; - VkMemoryDedicatedRequirements ded_req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - }; - VkMemoryRequirements2 req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &ded_req, - }; - - ret = vkCreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - req_desc.buffer = buf->buf; - - vkGetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); - - /* In case the implementation prefers/requires dedicated allocation */ - use_ded_mem = ded_req.prefersDedicatedAllocation | - ded_req.requiresDedicatedAllocation; - if (use_ded_mem) - ded_alloc.buffer = buf->buf; - - err = vk_alloc_mem(avctx, &req.memoryRequirements, flags, - use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, - &buf->flags, &buf->mem); - if (err) - return err; - - ret = vkBindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], - int nb_buffers, int invalidate) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - VkMappedMemoryRange *inval_list = NULL; - int inval_count = 0; - - for (int i = 0; i < nb_buffers; i++) { - ret = vkMapMemory(s->hwctx->act_dev, buf[i].mem, 0, - VK_WHOLE_SIZE, 0, (void **)&mem[i]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - if (!invalidate) - return 0; - - for (int i = 0; i < nb_buffers; i++) { - const VkMappedMemoryRange ival_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, - .size = VK_WHOLE_SIZE, - }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - inval_list = av_fast_realloc(s->scratch, &s->scratch_size, - (++inval_count)*sizeof(*inval_list)); - if (!inval_list) - return AVERROR(ENOMEM); - inval_list[inval_count - 1] = ival_buf; - } - - if (inval_count) { - ret = vkInvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, - inval_list); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - return 0; -} - -int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, - int flush) -{ - int err = 0; - VkResult ret; - VulkanFilterContext *s = avctx->priv; - VkMappedMemoryRange *flush_list = NULL; - int flush_count = 0; - - if (flush) { - for (int i = 0; i < nb_buffers; i++) { - const VkMappedMemoryRange flush_buf = { - .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, - .memory = buf[i].mem, - .size = VK_WHOLE_SIZE, - }; - if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) - continue; - flush_list = av_fast_realloc(s->scratch, &s->scratch_size, - (++flush_count)*sizeof(*flush_list)); - if (!flush_list) - return AVERROR(ENOMEM); - flush_list[flush_count - 1] = flush_buf; - } - } - - if (flush_count) { - ret = vkFlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, - flush_list); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to flush memory: %s\n", - ff_vk_ret2str(ret)); - err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ - } - } - - for (int i = 0; i < nb_buffers; i++) - vkUnmapMemory(s->hwctx->act_dev, buf[i].mem); - - return err; -} - -void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf) -{ - VulkanFilterContext *s = avctx->priv; - if (!buf) - return; - - if (buf->buf != VK_NULL_HANDLE) - vkDestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); - if (buf->mem != VK_NULL_HANDLE) - vkFreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); -} - -int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, - int offset, int size, VkShaderStageFlagBits stage) -{ - VkPushConstantRange *pc; - - pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts), - pl->push_consts_num + 1); - if (!pl->push_consts) - return AVERROR(ENOMEM); - - pc = &pl->push_consts[pl->push_consts_num++]; - memset(pc, 0, sizeof(*pc)); - - pc->stageFlags = stage; - pc->offset = offset; - pc->size = size; - - return 0; -} - -FN_CREATING(VulkanFilterContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx) -{ - VkResult ret; - FFVkExecContext *e; - VulkanFilterContext *s = avctx->priv; - - int queue_family = s->queue_family_idx; - int nb_queues = s->queue_count; - - VkCommandPoolCreateInfo cqueue_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, - .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, - .queueFamilyIndex = queue_family, - }; - VkCommandBufferAllocateInfo cbuf_create = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, - .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, - .commandBufferCount = nb_queues, - }; - - e = create_exec_ctx(s); - if (!e) - return AVERROR(ENOMEM); - - e->queues = av_mallocz(nb_queues * sizeof(*e->queues)); - if (!e->queues) - return AVERROR(ENOMEM); - - e->bufs = av_mallocz(nb_queues * sizeof(*e->bufs)); - if (!e->bufs) - return AVERROR(ENOMEM); - - /* Create command pool */ - ret = vkCreateCommandPool(s->hwctx->act_dev, &cqueue_create, - s->hwctx->alloc, &e->pool); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Command pool creation failure: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - cbuf_create.commandPool = e->pool; - - /* Allocate command buffer */ - ret = vkAllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - for (int i = 0; i < nb_queues; i++) { - FFVkQueueCtx *q = &e->queues[i]; - vkGetDeviceQueue(s->hwctx->act_dev, queue_family, i, &q->queue); - } - - *ctx = e; - - return 0; -} - -void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e) -{ - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; - - for (int j = 0; j < q->nb_buf_deps; j++) - av_buffer_unref(&q->buf_deps[j]); - q->nb_buf_deps = 0; - - for (int j = 0; j < q->nb_frame_deps; j++) - av_frame_free(&q->frame_deps[j]); - q->nb_frame_deps = 0; - - e->sem_wait_cnt = 0; - e->sem_sig_cnt = 0; -} - -int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; - - VkCommandBufferBeginInfo cmd_start = { - .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, - .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, - }; - - /* Create the fence and don't wait for it initially */ - if (!q->fence) { - VkFenceCreateInfo fence_spawn = { - .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, - }; - ret = vkCreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, - &q->fence); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } else { - vkWaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vkResetFences(s->hwctx->act_dev, 1, &q->fence); - } - - /* Discard queue dependencies */ - ff_vk_discard_exec_deps(avctx, e); - - ret = vkBeginCommandBuffer(e->bufs[s->cur_queue_idx], &cmd_start); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to start command recoding: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - return 0; -} - -VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e) -{ - VulkanFilterContext *s = avctx->priv; - return e->bufs[s->cur_queue_idx]; -} - -int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, - AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag) -{ - AVFrame **dst; - VulkanFilterContext *s = avctx->priv; - AVVkFrame *f = (AVVkFrame *)frame->data[0]; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; - AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data; - int planes = av_pix_fmt_count_planes(fc->sw_format); - - for (int i = 0; i < planes; i++) { - e->sem_wait = av_fast_realloc(e->sem_wait, &e->sem_wait_alloc, - (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait)); - if (!e->sem_wait) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_wait_dst = av_fast_realloc(e->sem_wait_dst, &e->sem_wait_dst_alloc, - (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst)); - if (!e->sem_wait_dst) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc, - (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig)); - if (!e->sem_sig) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - e->sem_wait[e->sem_wait_cnt] = f->sem[i]; - e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; - e->sem_wait_cnt++; - - e->sem_sig[e->sem_sig_cnt] = f->sem[i]; - e->sem_sig_cnt++; - } - - dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size, - (q->nb_frame_deps + 1) * sizeof(*dst)); - if (!dst) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - - q->frame_deps = dst; - q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame); - if (!q->frame_deps[q->nb_frame_deps]) { - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); - } - q->nb_frame_deps++; - - return 0; -} - -int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; - - VkSubmitInfo s_info = { - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &e->bufs[s->cur_queue_idx], - - .pWaitSemaphores = e->sem_wait, - .pWaitDstStageMask = e->sem_wait_dst, - .waitSemaphoreCount = e->sem_wait_cnt, - - .pSignalSemaphores = e->sem_sig, - .signalSemaphoreCount = e->sem_sig_cnt, - }; - - ret = vkEndCommandBuffer(e->bufs[s->cur_queue_idx]); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - ret = vkQueueSubmit(q->queue, 1, &s_info, q->fence); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - /* Rotate queues */ - s->cur_queue_idx = (s->cur_queue_idx + 1) % s->queue_count; - - return 0; -} - -int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e, - AVBufferRef **deps, int nb_deps) -{ - AVBufferRef **dst; - VulkanFilterContext *s = avctx->priv; - FFVkQueueCtx *q = &e->queues[s->cur_queue_idx]; - - if (!deps || !nb_deps) - return 0; - - dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size, - (q->nb_buf_deps + nb_deps) * sizeof(*dst)); - if (!dst) - goto err; - - q->buf_deps = dst; - - for (int i = 0; i < nb_deps; i++) { - q->buf_deps[q->nb_buf_deps] = deps[i]; - if (!q->buf_deps[q->nb_buf_deps]) - goto err; - q->nb_buf_deps++; - } - - return 0; - -err: - ff_vk_discard_exec_deps(avctx, e); - return AVERROR(ENOMEM); -} - -static int vulkan_filter_set_device(AVFilterContext *avctx, - AVBufferRef *device) -{ - VulkanFilterContext *s = avctx->priv; - - av_buffer_unref(&s->device_ref); - - s->device_ref = av_buffer_ref(device); - if (!s->device_ref) - return AVERROR(ENOMEM); - - s->device = (AVHWDeviceContext*)s->device_ref->data; - s->hwctx = s->device->hwctx; - - return 0; -} - -static int vulkan_filter_set_frames(AVFilterContext *avctx, - AVBufferRef *frames) -{ - VulkanFilterContext *s = avctx->priv; - - av_buffer_unref(&s->frames_ref); - - s->frames_ref = av_buffer_ref(frames); - if (!s->frames_ref) - return AVERROR(ENOMEM); - - return 0; -} - -int ff_vk_filter_config_input(AVFilterLink *inlink) -{ - int err; - AVFilterContext *avctx = inlink->dst; - VulkanFilterContext *s = avctx->priv; - AVHWFramesContext *input_frames; - - if (!inlink->hw_frames_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "hardware frames context on the input.\n"); - return AVERROR(EINVAL); - } - - /* Extract the device and default output format from the first input. */ - if (avctx->inputs[0] != inlink) - return 0; - - input_frames = (AVHWFramesContext*)inlink->hw_frames_ctx->data; - if (input_frames->format != AV_PIX_FMT_VULKAN) - return AVERROR(EINVAL); - - err = vulkan_filter_set_device(avctx, input_frames->device_ref); - if (err < 0) - return err; - err = vulkan_filter_set_frames(avctx, inlink->hw_frames_ctx); - if (err < 0) - return err; - - /* Default output parameters match input parameters. */ - s->input_format = input_frames->sw_format; - if (s->output_format == AV_PIX_FMT_NONE) - s->output_format = input_frames->sw_format; - if (!s->output_width) - s->output_width = inlink->w; - if (!s->output_height) - s->output_height = inlink->h; - - return 0; -} - -int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) -{ - int err; - AVFilterContext *avctx = outlink->src; - VulkanFilterContext *s = avctx->priv; - - av_buffer_unref(&outlink->hw_frames_ctx); - - if (!s->device_ref) { - if (!avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "Vulkan device.\n"); - return AVERROR(EINVAL); - } - - err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); - if (err < 0) - return err; - } - - outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref); - if (!outlink->hw_frames_ctx) - return AVERROR(ENOMEM); - - outlink->w = s->output_width; - outlink->h = s->output_height; - - return 0; -} - -int ff_vk_filter_config_output(AVFilterLink *outlink) -{ - int err; - AVFilterContext *avctx = outlink->src; - VulkanFilterContext *s = avctx->priv; - AVBufferRef *output_frames_ref; - AVHWFramesContext *output_frames; - - av_buffer_unref(&outlink->hw_frames_ctx); - - if (!s->device_ref) { - if (!avctx->hw_device_ctx) { - av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " - "Vulkan device.\n"); - return AVERROR(EINVAL); - } - - err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); - if (err < 0) - return err; - } - - output_frames_ref = av_hwframe_ctx_alloc(s->device_ref); - if (!output_frames_ref) { - err = AVERROR(ENOMEM); - goto fail; - } - output_frames = (AVHWFramesContext*)output_frames_ref->data; - - output_frames->format = AV_PIX_FMT_VULKAN; - output_frames->sw_format = s->output_format; - output_frames->width = s->output_width; - output_frames->height = s->output_height; - - err = av_hwframe_ctx_init(output_frames_ref); - if (err < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " - "frames: %d.\n", err); - goto fail; - } - - outlink->hw_frames_ctx = output_frames_ref; - outlink->w = s->output_width; - outlink->h = s->output_height; - - return 0; -fail: - av_buffer_unref(&output_frames_ref); - return err; -} - -int ff_vk_filter_init(AVFilterContext *avctx) -{ - VulkanFilterContext *s = avctx->priv; - - s->output_format = AV_PIX_FMT_NONE; - - if (glslang_init()) - return AVERROR_EXTERNAL; - - return 0; -} - -FN_CREATING(VulkanFilterContext, VkSampler, sampler, samplers, samplers_num) -VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - - VkSamplerCreateInfo sampler_info = { - .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, - .magFilter = filt, - .minFilter = sampler_info.magFilter, - .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST : - VK_SAMPLER_MIPMAP_MODE_LINEAR, - .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, - .addressModeV = sampler_info.addressModeU, - .addressModeW = sampler_info.addressModeU, - .anisotropyEnable = VK_FALSE, - .compareOp = VK_COMPARE_OP_NEVER, - .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - .unnormalizedCoordinates = unnorm_coords, - }; - - VkSampler *sampler = create_sampler(s); - if (!sampler) - return NULL; - - ret = vkCreateSampler(s->hwctx->act_dev, &sampler_info, - s->hwctx->alloc, sampler); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init sampler: %s\n", - ff_vk_ret2str(ret)); - return NULL; - } - - return sampler; -} - -int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) -{ - if (pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || - pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_RGB24 || - pix_fmt == AV_PIX_FMT_BGR24 || pix_fmt == AV_PIX_FMT_RGB48 || - pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 || - pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0 || - pix_fmt == AV_PIX_FMT_0BGR || pix_fmt == AV_PIX_FMT_RGB0) - return 1; - return 0; -} - -const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixfmt); - const int high = desc->comp[0].depth > 8; - return high ? "rgba16f" : "rgba8"; -} - -typedef struct ImageViewCtx { - VkImageView view; -} ImageViewCtx; - -static void destroy_imageview(void *opaque, uint8_t *data) -{ - VulkanFilterContext *s = opaque; - ImageViewCtx *iv = (ImageViewCtx *)data; - vkDestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); - av_free(iv); -} - -int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, - VkImageView *v, VkImage img, VkFormat fmt, - const VkComponentMapping map) -{ - int err; - AVBufferRef *buf; - VulkanFilterContext *s = avctx->priv; - VkImageViewCreateInfo imgview_spawn = { - .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, - .pNext = NULL, - .image = img, - .viewType = VK_IMAGE_VIEW_TYPE_2D, - .format = fmt, - .components = map, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .baseMipLevel = 0, - .levelCount = 1, - .baseArrayLayer = 0, - .layerCount = 1, - }, - }; - - ImageViewCtx *iv = av_mallocz(sizeof(*iv)); - - VkResult ret = vkCreateImageView(s->hwctx->act_dev, &imgview_spawn, - s->hwctx->alloc, &iv->view); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Failed to create imageview: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0); - if (!buf) { - destroy_imageview(s, (uint8_t *)iv); - return AVERROR(ENOMEM); - } - - /* Add to queue dependencies */ - err = ff_vk_add_dep_exec_ctx(avctx, e, &buf, 1); - if (err) { - av_buffer_unref(&buf); - return err; - } - - *v = iv->view; - - return 0; -} - -FN_CREATING(VulkanPipeline, SPIRVShader, shader, shaders, shaders_num) -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage) -{ - SPIRVShader *shd = create_shader(pl); - if (!shd) - return NULL; - - av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED); - - shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shd->shader.stage = stage; - - shd->name = name; - - GLSLF(0, #version %i ,460); - GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) ); - GLSLC(0, ); - - return shd; -} - -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, - int local_size[3]) -{ - shd->local_size[0] = local_size[0]; - shd->local_size[1] = local_size[1]; - shd->local_size[2] = local_size[2]; - - av_bprintf(&shd->src, "layout (local_size_x = %i, " - "local_size_y = %i, local_size_z = %i) in;\n\n", - shd->local_size[0], shd->local_size[1], shd->local_size[2]); -} - -static void print_shader(AVFilterContext *avctx, SPIRVShader *shd, int prio) -{ - int line = 0; - const char *p = shd->src.str; - const char *start = p; - - AVBPrint buf; - av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - - for (int i = 0; i < strlen(p); i++) { - if (p[i] == '\n') { - av_bprintf(&buf, "%i\t", ++line); - av_bprint_append_data(&buf, start, &p[i] - start + 1); - start = &p[i + 1]; - } - } - - av_log(avctx, prio, "Shader %s: \n%s", shd->name, buf.str); - av_bprint_finalize(&buf, NULL); -} - -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, - const char *entrypoint) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - VkShaderModuleCreateInfo shader_create; - GLSlangResult *res; - - static const enum GLSlangStage emap[] = { - [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_VERTEX, - [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_FRAGMENT, - [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_COMPUTE, - }; - - shd->shader.pName = entrypoint; - - res = glslang_compile(shd->src.str, emap[shd->shader.stage]); - if (!res) - return AVERROR(ENOMEM); - - if (res->rval) { - av_log(avctx, AV_LOG_ERROR, "Error compiling shader %s: %s!\n", - shd->name, av_err2str(res->rval)); - print_shader(avctx, shd, AV_LOG_ERROR); - if (res->error_msg) - av_log(avctx, AV_LOG_ERROR, "%s", res->error_msg); - av_free(res->error_msg); - return res->rval; - } - - print_shader(avctx, shd, AV_LOG_VERBOSE); - - shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - shader_create.pNext = NULL; - shader_create.codeSize = res->size; - shader_create.flags = 0; - shader_create.pCode = res->data; - - ret = vkCreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, - &shd->shader.module); - - /* Free the GLSlangResult struct */ - av_free(res->data); - av_free(res); - - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to create shader module: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - av_log(avctx, AV_LOG_VERBOSE, "Shader %s linked! Size: %zu bytes\n", - shd->name, shader_create.codeSize); - - return 0; -} - -static const struct descriptor_props { - size_t struct_size; /* Size of the opaque which updates the descriptor */ - const char *type; - int is_uniform; - int mem_quali; /* Can use a memory qualifier */ - int dim_needed; /* Must indicate dimension */ - int buf_content; /* Must indicate buffer contents */ -} descriptor_props[] = { - [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, }, - [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, }, - [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, - [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, - [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, - [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, }, - [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, }, -}; - -int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, - int num, int only_print_to_shader) -{ - VkResult ret; - VkDescriptorSetLayout *layout; - VulkanFilterContext *s = avctx->priv; - - if (only_print_to_shader) - goto print; - - pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout), - pl->desc_layout_num + 1); - if (!pl->desc_layout) - return AVERROR(ENOMEM); - - layout = &pl->desc_layout[pl->desc_layout_num]; - memset(layout, 0, sizeof(*layout)); - - { /* Create descriptor set layout descriptions */ - VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 }; - VkDescriptorSetLayoutBinding *desc_binding; - - desc_binding = av_mallocz(sizeof(*desc_binding)*num); - if (!desc_binding) - return AVERROR(ENOMEM); - - for (int i = 0; i < num; i++) { - desc_binding[i].binding = i; - desc_binding[i].descriptorType = desc[i].type; - desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1); - desc_binding[i].stageFlags = desc[i].stages; - desc_binding[i].pImmutableSamplers = desc[i].samplers; - } - - desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - desc_create_layout.pBindings = desc_binding; - desc_create_layout.bindingCount = num; - - ret = vkCreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, - s->hwctx->alloc, layout); - av_free(desc_binding); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " - "layout: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Pool each descriptor by type and update pool counts */ - for (int i = 0; i < num; i++) { - int j; - for (j = 0; j < pl->pool_size_desc_num; j++) - if (pl->pool_size_desc[j].type == desc[i].type) - break; - if (j >= pl->pool_size_desc_num) { - pl->pool_size_desc = av_realloc_array(pl->pool_size_desc, - sizeof(*pl->pool_size_desc), - ++pl->pool_size_desc_num); - if (!pl->pool_size_desc) - return AVERROR(ENOMEM); - memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize)); - } - pl->pool_size_desc[j].type = desc[i].type; - pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1); - } - } - - { /* Create template creation struct */ - VkDescriptorUpdateTemplateCreateInfo *dt; - VkDescriptorUpdateTemplateEntry *des_entries; - - /* Freed after descriptor set initialization */ - des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry)); - if (!des_entries) - return AVERROR(ENOMEM); - - for (int i = 0; i < num; i++) { - des_entries[i].dstBinding = i; - des_entries[i].descriptorType = desc[i].type; - des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1); - des_entries[i].dstArrayElement = 0; - des_entries[i].offset = ((uint8_t *)desc[i].updater) - (uint8_t *)s; - des_entries[i].stride = descriptor_props[desc[i].type].struct_size; - } - - pl->desc_template_info = av_realloc_array(pl->desc_template_info, - sizeof(*pl->desc_template_info), - pl->desc_layout_num + 1); - if (!pl->desc_template_info) - return AVERROR(ENOMEM); - - dt = &pl->desc_template_info[pl->desc_layout_num]; - memset(dt, 0, sizeof(*dt)); - - dt->sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; - dt->templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; - dt->descriptorSetLayout = *layout; - dt->pDescriptorUpdateEntries = des_entries; - dt->descriptorUpdateEntryCount = num; - } - - pl->desc_layout_num++; - -print: - /* Write shader info */ - for (int i = 0; i < num; i++) { - const struct descriptor_props *prop = &descriptor_props[desc[i].type]; - GLSLA("layout (set = %i, binding = %i", pl->desc_layout_num - 1, i); - - if (desc[i].mem_layout) - GLSLA(", %s", desc[i].mem_layout); - GLSLA(")"); - - if (prop->is_uniform) - GLSLA(" uniform"); - - if (prop->mem_quali && desc[i].mem_quali) - GLSLA(" %s", desc[i].mem_quali); - - if (prop->type) - GLSLA(" %s", prop->type); - - if (prop->dim_needed) - GLSLA("%iD", desc[i].dimensions); - - GLSLA(" %s", desc[i].name); - - if (prop->buf_content) - GLSLA(" {\n %s\n}", desc[i].buf_content); - else if (desc[i].elems > 0) - GLSLA("[%i]", desc[i].elems); - - GLSLA(";\n"); - } - GLSLA("\n"); - - return 0; -} - -void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - int set_id) -{ - VulkanFilterContext *s = avctx->priv; - - vkUpdateDescriptorSetWithTemplate(s->hwctx->act_dev, - pl->desc_set[s->cur_queue_idx * pl->desc_layout_num + set_id], - pl->desc_template[set_id], - s); -} - -void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src) -{ - VulkanFilterContext *s = avctx->priv; - vkCmdPushConstants(e->bufs[s->cur_queue_idx], e->bound_pl->pipeline_layout, - stage, offset, size, src); -} - -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl) -{ - VkResult ret; - VulkanFilterContext *s = avctx->priv; - - pl->descriptor_sets_num = pl->desc_layout_num * s->queue_count; - - { /* Init descriptor set pool */ - VkDescriptorPoolCreateInfo pool_create_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = pl->pool_size_desc_num, - .pPoolSizes = pl->pool_size_desc, - .maxSets = pl->descriptor_sets_num, - }; - - ret = vkCreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, - s->hwctx->alloc, &pl->desc_pool); - av_freep(&pl->pool_size_desc); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor set " - "pool: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Allocate descriptor sets */ - VkDescriptorSetAllocateInfo alloc_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, - .descriptorPool = pl->desc_pool, - .descriptorSetCount = pl->descriptor_sets_num, - .pSetLayouts = pl->desc_layout, - }; - - pl->desc_set = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_set)); - if (!pl->desc_set) - return AVERROR(ENOMEM); - - ret = vkAllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, - pl->desc_set); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Finally create the pipeline layout */ - VkPipelineLayoutCreateInfo spawn_pipeline_layout = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - .setLayoutCount = pl->desc_layout_num, - .pSetLayouts = pl->desc_layout, - .pushConstantRangeCount = pl->push_consts_num, - .pPushConstantRanges = pl->push_consts, - }; - - ret = vkCreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, - s->hwctx->alloc, &pl->pipeline_layout); - av_freep(&pl->push_consts); - pl->push_consts_num = 0; - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - { /* Descriptor template (for tightly packed descriptors) */ - VkDescriptorUpdateTemplateCreateInfo *desc_template_info; - - pl->desc_template = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_template)); - if (!pl->desc_template) - return AVERROR(ENOMEM); - - /* Create update templates for the descriptor sets */ - for (int i = 0; i < pl->descriptor_sets_num; i++) { - desc_template_info = &pl->desc_template_info[i % pl->desc_layout_num]; - desc_template_info->pipelineLayout = pl->pipeline_layout; - ret = vkCreateDescriptorUpdateTemplate(s->hwctx->act_dev, - desc_template_info, - s->hwctx->alloc, - &pl->desc_template[i]); - av_free((void *)desc_template_info->pDescriptorUpdateEntries); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init descriptor " - "template: %s\n", ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - } - - av_freep(&pl->desc_template_info); - } - - return 0; -} - -FN_CREATING(VulkanFilterContext, VulkanPipeline, pipeline, pipelines, pipelines_num) -VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx) -{ - return create_pipeline(avctx->priv); -} - -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl) -{ - int i; - VkResult ret; - VulkanFilterContext *s = avctx->priv; - - VkComputePipelineCreateInfo pipe = { - .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, - .layout = pl->pipeline_layout, - }; - - for (i = 0; i < pl->shaders_num; i++) { - if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) { - pipe.stage = pl->shaders[i]->shader; - break; - } - } - if (i == pl->shaders_num) { - av_log(avctx, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n"); - return AVERROR(EINVAL); - } - - ret = vkCreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, - s->hwctx->alloc, &pl->pipeline); - if (ret != VK_SUCCESS) { - av_log(avctx, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", - ff_vk_ret2str(ret)); - return AVERROR_EXTERNAL; - } - - pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; - - return 0; -} - -void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - VulkanPipeline *pl) -{ - VulkanFilterContext *s = avctx->priv; - - vkCmdBindPipeline(e->bufs[s->cur_queue_idx], pl->bind_point, pl->pipeline); - - vkCmdBindDescriptorSets(e->bufs[s->cur_queue_idx], pl->bind_point, - pl->pipeline_layout, 0, pl->descriptor_sets_num, - pl->desc_set, 0, 0); - - e->bound_pl = pl; -} - -static void free_exec_ctx(VulkanFilterContext *s, FFVkExecContext *e) -{ - /* Make sure all queues have finished executing */ - for (int i = 0; i < s->queue_count; i++) { - FFVkQueueCtx *q = &e->queues[i]; - - if (q->fence) { - vkWaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); - vkResetFences(s->hwctx->act_dev, 1, &q->fence); - } - - /* Free the fence */ - if (q->fence) - vkDestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); - - /* Free buffer dependencies */ - for (int j = 0; j < q->nb_buf_deps; j++) - av_buffer_unref(&q->buf_deps[j]); - av_free(q->buf_deps); - - /* Free frame dependencies */ - for (int j = 0; j < q->nb_frame_deps; j++) - av_frame_free(&q->frame_deps[j]); - av_free(q->frame_deps); - } - - if (e->bufs) - vkFreeCommandBuffers(s->hwctx->act_dev, e->pool, s->queue_count, e->bufs); - if (e->pool) - vkDestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); - - av_freep(&e->bufs); - av_freep(&e->queues); - av_freep(&e->sem_sig); - av_freep(&e->sem_wait); - av_freep(&e->sem_wait_dst); - av_free(e); -} - -static void free_pipeline(VulkanFilterContext *s, VulkanPipeline *pl) -{ - for (int i = 0; i < pl->shaders_num; i++) { - SPIRVShader *shd = pl->shaders[i]; - av_bprint_finalize(&shd->src, NULL); - vkDestroyShaderModule(s->hwctx->act_dev, shd->shader.module, - s->hwctx->alloc); - av_free(shd); - } - - vkDestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); - vkDestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, - s->hwctx->alloc); - - for (int i = 0; i < pl->desc_layout_num; i++) { - if (pl->desc_template && pl->desc_template[i]) - vkDestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], - s->hwctx->alloc); - if (pl->desc_layout && pl->desc_layout[i]) - vkDestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], - s->hwctx->alloc); - } - - /* Also frees the descriptor sets */ - if (pl->desc_pool) - vkDestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, - s->hwctx->alloc); - - av_freep(&pl->desc_set); - av_freep(&pl->shaders); - av_freep(&pl->desc_layout); - av_freep(&pl->desc_template); - av_freep(&pl->push_consts); - pl->push_consts_num = 0; - - /* Only freed in case of failure */ - av_freep(&pl->pool_size_desc); - if (pl->desc_template_info) { - for (int i = 0; i < pl->descriptor_sets_num; i++) - av_free((void *)pl->desc_template_info[i].pDescriptorUpdateEntries); - av_freep(&pl->desc_template_info); - } - - av_free(pl); -} - -void ff_vk_filter_uninit(AVFilterContext *avctx) -{ - VulkanFilterContext *s = avctx->priv; - - glslang_uninit(); - - for (int i = 0; i < s->exec_ctx_num; i++) - free_exec_ctx(s, s->exec_ctx[i]); - av_freep(&s->exec_ctx); - - for (int i = 0; i < s->samplers_num; i++) { - vkDestroySampler(s->hwctx->act_dev, *s->samplers[i], s->hwctx->alloc); - av_free(s->samplers[i]); - } - av_freep(&s->samplers); - - for (int i = 0; i < s->pipelines_num; i++) - free_pipeline(s, s->pipelines[i]); - av_freep(&s->pipelines); - - av_freep(&s->scratch); - s->scratch_size = 0; - - av_buffer_unref(&s->device_ref); - av_buffer_unref(&s->frames_ref); -} +#include "libavutil/vulkan.c" diff --git a/libavfilter/vulkan.h b/libavfilter/vulkan.h index d4a03abfe9..928b2e21c3 100644 --- a/libavfilter/vulkan.h +++ b/libavfilter/vulkan.h @@ -19,357 +19,6 @@ #ifndef AVFILTER_VULKAN_H #define AVFILTER_VULKAN_H -#include "avfilter.h" -#include "libavutil/pixdesc.h" -#include "libavutil/bprint.h" -#include "libavutil/hwcontext.h" -#include "libavutil/hwcontext_vulkan.h" - -/* GLSL management macros */ -#define INDENT(N) INDENT_##N -#define INDENT_0 -#define INDENT_1 INDENT_0 " " -#define INDENT_2 INDENT_1 INDENT_1 -#define INDENT_3 INDENT_2 INDENT_1 -#define INDENT_4 INDENT_3 INDENT_1 -#define INDENT_5 INDENT_4 INDENT_1 -#define INDENT_6 INDENT_5 INDENT_1 -#define C(N, S) INDENT(N) #S "\n" -#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S)) -#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__) -#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__) -#define GLSLD(D) GLSLC(0, ); \ - av_bprint_append_data(&shd->src, D, strlen(D)); \ - GLSLC(0, ) - -/* Helper, pretty much every Vulkan return value needs to be checked */ -#define RET(x) \ - do { \ - if ((err = (x)) < 0) \ - goto fail; \ - } while (0) - -/* Gets the queues count for a single queue family */ -#define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ - graph ? hwctx->nb_graphics_queues : \ - comp ? (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ - tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ - (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ - 0 \ -) - -/* Useful for attaching immutable samplers to arrays */ -#define DUP_SAMPLER_ARRAY4(x) (VkSampler []){ x, x, x, x, } - -typedef struct SPIRVShader { - const char *name; /* Name for id/debugging purposes */ - AVBPrint src; - int local_size[3]; /* Compute shader workgroup sizes */ - VkPipelineShaderStageCreateInfo shader; -} SPIRVShader; - -typedef struct VulkanDescriptorSetBinding { - const char *name; - VkDescriptorType type; - const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */ - const char *mem_quali; /* readonly, writeonly, etc. */ - const char *buf_content; /* For buffers */ - uint32_t dimensions; /* Needed for e.g. sampler%iD */ - uint32_t elems; /* 0 - scalar, 1 or more - vector */ - VkShaderStageFlags stages; - const VkSampler *samplers; /* Immutable samplers, length - #elems */ - void *updater; /* Pointer to VkDescriptor*Info */ -} VulkanDescriptorSetBinding; - -typedef struct FFVkBuffer { - VkBuffer buf; - VkDeviceMemory mem; - VkMemoryPropertyFlagBits flags; -} FFVkBuffer; - -typedef struct VulkanPipeline { - VkPipelineBindPoint bind_point; - - /* Contexts */ - VkPipelineLayout pipeline_layout; - VkPipeline pipeline; - - /* Shaders */ - SPIRVShader **shaders; - int shaders_num; - - /* Push consts */ - VkPushConstantRange *push_consts; - int push_consts_num; - - /* Descriptors */ - VkDescriptorSetLayout *desc_layout; - VkDescriptorPool desc_pool; - VkDescriptorSet *desc_set; - VkDescriptorUpdateTemplate *desc_template; - int desc_layout_num; - int descriptor_sets_num; - int pool_size_desc_num; - - /* Temporary, used to store data in between initialization stages */ - VkDescriptorUpdateTemplateCreateInfo *desc_template_info; - VkDescriptorPoolSize *pool_size_desc; -} VulkanPipeline; - -typedef struct FFVkQueueCtx { - VkFence fence; - VkQueue queue; - - /* Buffer dependencies */ - AVBufferRef **buf_deps; - int nb_buf_deps; - int buf_deps_alloc_size; - - /* Frame dependencies */ - AVFrame **frame_deps; - int nb_frame_deps; - int frame_deps_alloc_size; -} FFVkQueueCtx; - -typedef struct FFVkExecContext { - VkCommandPool pool; - VkCommandBuffer *bufs; - FFVkQueueCtx *queues; - - AVBufferRef ***deps; - int *nb_deps; - int *dep_alloc_size; - - VulkanPipeline *bound_pl; - - VkSemaphore *sem_wait; - int sem_wait_alloc; /* Allocated sem_wait */ - int sem_wait_cnt; - - VkPipelineStageFlagBits *sem_wait_dst; - int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ - - VkSemaphore *sem_sig; - int sem_sig_alloc; /* Allocated sem_sig */ - int sem_sig_cnt; -} FFVkExecContext; - -typedef struct VulkanFilterContext { - const AVClass *class; - - AVBufferRef *device_ref; - AVBufferRef *frames_ref; /* For in-place filtering */ - AVHWDeviceContext *device; - AVVulkanDeviceContext *hwctx; - - /* State - mirrored with the exec ctx */ - int cur_queue_idx; - int queue_family_idx; - int queue_count; - - /* Properties */ - int output_width; - int output_height; - enum AVPixelFormat output_format; - enum AVPixelFormat input_format; - - /* Samplers */ - VkSampler **samplers; - int samplers_num; - - /* Exec contexts */ - FFVkExecContext **exec_ctx; - int exec_ctx_num; - - /* Pipelines (each can have 1 shader of each type) */ - VulkanPipeline **pipelines; - int pipelines_num; - - void *scratch; /* Scratch memory used only in functions */ - unsigned int scratch_size; -} VulkanFilterContext; - -/* Identity mapping - r = r, b = b, g = g, a = a */ -extern const VkComponentMapping ff_comp_identity_map; - -/** - * General lavfi IO functions - */ -int ff_vk_filter_init (AVFilterContext *avctx); -int ff_vk_filter_config_input (AVFilterLink *inlink); -int ff_vk_filter_config_output (AVFilterLink *outlink); -int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); -void ff_vk_filter_uninit (AVFilterContext *avctx); - -/** - * Converts Vulkan return values to strings - */ -const char *ff_vk_ret2str(VkResult res); - -/** - * Returns 1 if the image is any sort of supported RGB - */ -int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); - -/** - * Gets the glsl format string for a pixel format - */ -const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); - -/** - * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() - */ -VkSampler *ff_vk_init_sampler(AVFilterContext *avctx, int unnorm_coords, - VkFilter filt); - -/** - * Create an imageview. - * Guaranteed to remain alive until the queue submission has finished executing, - * and will be destroyed after that. - */ -int ff_vk_create_imageview(AVFilterContext *avctx, FFVkExecContext *e, - VkImageView *v, VkImage img, VkFormat fmt, - const VkComponentMapping map); - -/** - * Define a push constant for a given stage into a pipeline. - * Must be called before the pipeline layout has been initialized. - */ -int ff_vk_add_push_constant(AVFilterContext *avctx, VulkanPipeline *pl, - int offset, int size, VkShaderStageFlagBits stage); - -/** - * Inits a pipeline. Everything in it will be auto-freed when calling - * ff_vk_filter_uninit(). - */ -VulkanPipeline *ff_vk_create_pipeline(AVFilterContext *avctx); - -/** - * Inits a shader for a specific pipeline. Will be auto-freed on uninit. - */ -SPIRVShader *ff_vk_init_shader(AVFilterContext *avctx, VulkanPipeline *pl, - const char *name, VkShaderStageFlags stage); - -/** - * Writes the workgroup size for a shader. - */ -void ff_vk_set_compute_shader_sizes(AVFilterContext *avctx, SPIRVShader *shd, - int local_size[3]); - -/** - * Adds a descriptor set to the shader and registers them in the pipeline. - */ -int ff_vk_add_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - SPIRVShader *shd, VulkanDescriptorSetBinding *desc, - int num, int only_print_to_shader); - -/** - * Compiles the shader, entrypoint must be set to "main". - */ -int ff_vk_compile_shader(AVFilterContext *avctx, SPIRVShader *shd, - const char *entrypoint); - -/** - * Initializes the pipeline layout after all shaders and descriptor sets have - * been finished. - */ -int ff_vk_init_pipeline_layout(AVFilterContext *avctx, VulkanPipeline *pl); - -/** - * Initializes a compute pipeline. Will pick the first shader with the - * COMPUTE flag set. - */ -int ff_vk_init_compute_pipeline(AVFilterContext *avctx, VulkanPipeline *pl); - -/** - * Updates a descriptor set via the updaters defined. - * Can be called immediately after pipeline creation, but must be called - * at least once before queue submission. - */ -void ff_vk_update_descriptor_set(AVFilterContext *avctx, VulkanPipeline *pl, - int set_id); - -/** - * Init an execution context for command recording and queue submission. - * WIll be auto-freed on uninit. - */ -int ff_vk_create_exec_ctx(AVFilterContext *avctx, FFVkExecContext **ctx); - -/** - * Begin recording to the command buffer. Previous execution must have been - * completed, which ff_vk_submit_exec_queue() will ensure. - */ -int ff_vk_start_exec_recording(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Add a command to bind the completed pipeline and its descriptor sets. - * Must be called after ff_vk_start_exec_recording() and before submission. - */ -void ff_vk_bind_pipeline_exec(AVFilterContext *avctx, FFVkExecContext *e, - VulkanPipeline *pl); - -/** - * Updates push constants. - * Must be called after binding a pipeline if any push constants were defined. - */ -void ff_vk_update_push_exec(AVFilterContext *avctx, FFVkExecContext *e, - VkShaderStageFlagBits stage, int offset, - size_t size, void *src); - -/** - * Gets the command buffer to use for this submission from the exe context. - */ -VkCommandBuffer ff_vk_get_exec_buf(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Adds a generic AVBufferRef as a queue depenency. - */ -int ff_vk_add_dep_exec_ctx(AVFilterContext *avctx, FFVkExecContext *e, - AVBufferRef **deps, int nb_deps); - -/** - * Discards all queue dependencies - */ -void ff_vk_discard_exec_deps(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Adds a frame as a queue dependency. This also manages semaphore signalling. - * Must be called before submission. - */ -int ff_vk_add_exec_dep(AVFilterContext *avctx, FFVkExecContext *e, - AVFrame *frame, VkPipelineStageFlagBits in_wait_dst_flag); - -/** - * Submits a command buffer to the queue for execution. - * Will block until execution has finished in order to simplify resource - * management. - */ -int ff_vk_submit_exec_queue(AVFilterContext *avctx, FFVkExecContext *e); - -/** - * Create a VkBuffer with the specified parameters. - */ -int ff_vk_create_buf(AVFilterContext *avctx, FFVkBuffer *buf, size_t size, - VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); - -/** - * Maps the buffer to userspace. Set invalidate to 1 if reading the contents - * is necessary. - */ -int ff_vk_map_buffers(AVFilterContext *avctx, FFVkBuffer *buf, uint8_t *mem[], - int nb_buffers, int invalidate); - -/** - * Unmaps the buffer from userspace. Set flush to 1 to write and sync. - */ -int ff_vk_unmap_buffers(AVFilterContext *avctx, FFVkBuffer *buf, int nb_buffers, - int flush); - -/** - * Frees a buffer. - */ -void ff_vk_free_buf(AVFilterContext *avctx, FFVkBuffer *buf); +#include "libavutil/vulkan.h" #endif /* AVFILTER_VULKAN_H */ diff --git a/libavfilter/vulkan_filter.c b/libavfilter/vulkan_filter.c new file mode 100644 index 0000000000..e22541bd23 --- /dev/null +++ b/libavfilter/vulkan_filter.c @@ -0,0 +1,191 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "vulkan_filter.h" + +static int vulkan_filter_set_device(AVFilterContext *avctx, + AVBufferRef *device) +{ + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&s->device_ref); + + s->device_ref = av_buffer_ref(device); + if (!s->device_ref) + return AVERROR(ENOMEM); + + s->device = (AVHWDeviceContext*)s->device_ref->data; + s->hwctx = s->device->hwctx; + + return 0; +} + +static int vulkan_filter_set_frames(AVFilterContext *avctx, + AVBufferRef *frames) +{ + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&s->frames_ref); + + s->frames_ref = av_buffer_ref(frames); + if (!s->frames_ref) + return AVERROR(ENOMEM); + + return 0; +} + +int ff_vk_filter_config_input(AVFilterLink *inlink) +{ + int err; + AVFilterContext *avctx = inlink->dst; + FFVulkanContext *s = avctx->priv; + FFVulkanFunctions *vk = &s->vkfn; + AVHWFramesContext *input_frames; + + if (!inlink->hw_frames_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "hardware frames context on the input.\n"); + return AVERROR(EINVAL); + } + + /* Extract the device and default output format from the first input. */ + if (avctx->inputs[0] != inlink) + return 0; + + input_frames = (AVHWFramesContext *)inlink->hw_frames_ctx->data; + if (input_frames->format != AV_PIX_FMT_VULKAN) + return AVERROR(EINVAL); + + err = vulkan_filter_set_device(avctx, input_frames->device_ref); + if (err < 0) + return err; + err = vulkan_filter_set_frames(avctx, inlink->hw_frames_ctx); + if (err < 0) + return err; + + s->extensions = ff_vk_extensions_to_mask(s->hwctx->enabled_dev_extensions, + s->hwctx->nb_enabled_dev_extensions); + + err = ff_vk_load_functions(s->device, &s->vkfn, s->extensions, 1, 1); + if (err < 0) + return err; + + vk->GetPhysicalDeviceProperties(s->hwctx->phys_dev, &s->props); + vk->GetPhysicalDeviceMemoryProperties(s->hwctx->phys_dev, &s->mprops); + + /* Default output parameters match input parameters. */ + s->input_format = input_frames->sw_format; + if (s->output_format == AV_PIX_FMT_NONE) + s->output_format = input_frames->sw_format; + if (!s->output_width) + s->output_width = inlink->w; + if (!s->output_height) + s->output_height = inlink->h; + + return 0; +} + +int ff_vk_filter_config_output_inplace(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + FFVulkanContext *s = avctx->priv; + + av_buffer_unref(&outlink->hw_frames_ctx); + + if (!s->device_ref) { + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "Vulkan device.\n"); + return AVERROR(EINVAL); + } + + err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); + if (err < 0) + return err; + } + + outlink->hw_frames_ctx = av_buffer_ref(s->frames_ref); + if (!outlink->hw_frames_ctx) + return AVERROR(ENOMEM); + + outlink->w = s->output_width; + outlink->h = s->output_height; + + return 0; +} + +int ff_vk_filter_config_output(AVFilterLink *outlink) +{ + int err; + AVFilterContext *avctx = outlink->src; + FFVulkanContext *s = avctx->priv; + AVBufferRef *output_frames_ref; + AVHWFramesContext *output_frames; + + av_buffer_unref(&outlink->hw_frames_ctx); + + if (!s->device_ref) { + if (!avctx->hw_device_ctx) { + av_log(avctx, AV_LOG_ERROR, "Vulkan filtering requires a " + "Vulkan device.\n"); + return AVERROR(EINVAL); + } + + err = vulkan_filter_set_device(avctx, avctx->hw_device_ctx); + if (err < 0) + return err; + } + + output_frames_ref = av_hwframe_ctx_alloc(s->device_ref); + if (!output_frames_ref) { + err = AVERROR(ENOMEM); + goto fail; + } + output_frames = (AVHWFramesContext*)output_frames_ref->data; + + output_frames->format = AV_PIX_FMT_VULKAN; + output_frames->sw_format = s->output_format; + output_frames->width = s->output_width; + output_frames->height = s->output_height; + + err = av_hwframe_ctx_init(output_frames_ref); + if (err < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to initialise output " + "frames: %d.\n", err); + goto fail; + } + + outlink->hw_frames_ctx = output_frames_ref; + outlink->w = s->output_width; + outlink->h = s->output_height; + + return 0; +fail: + av_buffer_unref(&output_frames_ref); + return err; +} + +int ff_vk_filter_init(AVFilterContext *avctx) +{ + FFVulkanContext *s = avctx->priv; + + s->output_format = AV_PIX_FMT_NONE; + + return 0; +} diff --git a/libavfilter/vulkan_filter.h b/libavfilter/vulkan_filter.h new file mode 100644 index 0000000000..bfdb9b2d7d --- /dev/null +++ b/libavfilter/vulkan_filter.h @@ -0,0 +1,34 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VULKAN_FILTER_H +#define AVFILTER_VULKAN_FILTER_H + +#include "avfilter.h" + +#include "vulkan.h" + +/** + * General lavfi IO functions + */ +int ff_vk_filter_init (AVFilterContext *avctx); +int ff_vk_filter_config_input (AVFilterLink *inlink); +int ff_vk_filter_config_output (AVFilterLink *outlink); +int ff_vk_filter_config_output_inplace(AVFilterLink *outlink); + +#endif /* AVFILTER_VULKAN_FILTER_H */ diff --git a/libavfilter/x86/Makefile b/libavfilter/x86/Makefile index a29941eaeb..e87481bd7a 100644 --- a/libavfilter/x86/Makefile +++ b/libavfilter/x86/Makefile @@ -20,6 +20,7 @@ OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter_init.o OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d_init.o OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp_init.o OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge_init.o +OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans_init.o OBJS-$(CONFIG_NOISE_FILTER) += x86/vf_noise.o OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay_init.o OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7_init.o @@ -61,6 +62,7 @@ X86ASM-OBJS-$(CONFIG_LIMITER_FILTER) += x86/vf_limiter.o X86ASM-OBJS-$(CONFIG_LUT3D_FILTER) += x86/vf_lut3d.o X86ASM-OBJS-$(CONFIG_MASKEDCLAMP_FILTER) += x86/vf_maskedclamp.o X86ASM-OBJS-$(CONFIG_MASKEDMERGE_FILTER) += x86/vf_maskedmerge.o +X86ASM-OBJS-$(CONFIG_NLMEANS_FILTER) += x86/vf_nlmeans.o X86ASM-OBJS-$(CONFIG_OVERLAY_FILTER) += x86/vf_overlay.o X86ASM-OBJS-$(CONFIG_PP7_FILTER) += x86/vf_pp7.o X86ASM-OBJS-$(CONFIG_PSNR_FILTER) += x86/vf_psnr.o diff --git a/libavfilter/x86/vf_nlmeans.asm b/libavfilter/x86/vf_nlmeans.asm new file mode 100644 index 0000000000..8f57801035 --- /dev/null +++ b/libavfilter/x86/vf_nlmeans.asm @@ -0,0 +1,97 @@ +;***************************************************************************** +;* x86-optimized functions for nlmeans filter +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + + +%include "libavutil/x86/x86util.asm" + +%if HAVE_AVX2_EXTERNAL && ARCH_X86_64 + +SECTION_RODATA 32 + +ending_lut: dd -1, -1, -1, -1, -1, -1, -1, -1,\ + 0, -1, -1, -1, -1, -1, -1, -1,\ + 0, 0, -1, -1, -1, -1, -1, -1,\ + 0, 0, 0, -1, -1, -1, -1, -1,\ + 0, 0, 0, 0, -1, -1, -1, -1,\ + 0, 0, 0, 0, 0, -1, -1, -1,\ + 0, 0, 0, 0, 0, 0, -1, -1,\ + 0, 0, 0, 0, 0, 0, 0, -1,\ + 0, 0, 0, 0, 0, 0, 0, 0 + +SECTION .text + +; void ff_compute_weights_line(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, +; float *sum, +; const float *const lut, +; int max, +; int startx, int endx); + +INIT_YMM avx2 +cglobal compute_weights_line, 8, 13, 5, 0, iia, iib, iid, iie, src, total, sum, lut, x, startx, endx, mod, elut + movsxd startxq, dword startxm + movsxd endxq, dword endxm + VPBROADCASTD m2, r8m + + mov xq, startxq + mov modq, mmsize / 4 + lea elutq, [ending_lut] + + vpcmpeqd m4, m4 + + .loop: + mov startxq, endxq + sub startxq, xq + cmp startxq, modq + cmovge startxq, modq + sal startxq, 5 + + movu m0, [iieq + xq * 4] + + psubd m0, [iidq + xq * 4] + psubd m0, [iibq + xq * 4] + paddd m0, [iiaq + xq * 4] + por m0, [elutq + startxq] + pminud m0, m2 + pslld m0, 2 + mova m3, m4 + vgatherdps m1, [lutq + m0], m3 + + pmovzxbd m0, [srcq + xq] + cvtdq2ps m0, m0 + + mulps m0, m1 + + addps m1, [totalq + xq * 4] + addps m0, [sumq + xq * 4] + + movups [totalq + xq * 4], m1 + movups [sumq + xq * 4], m0 + + add xq, mmsize / 4 + cmp xq, endxq + jl .loop + RET + +%endif diff --git a/libavfilter/x86/vf_nlmeans_init.c b/libavfilter/x86/vf_nlmeans_init.c new file mode 100644 index 0000000000..37764d30ab --- /dev/null +++ b/libavfilter/x86/vf_nlmeans_init.c @@ -0,0 +1,40 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/attributes.h" +#include "libavutil/x86/cpu.h" +#include "libavfilter/vf_nlmeans.h" + +void ff_compute_weights_line_avx2(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); + +av_cold void ff_nlmeans_init_x86(NLMeansDSPContext *dsp) +{ + int cpu_flags = av_get_cpu_flags(); + + if (ARCH_X86_64 && EXTERNAL_AVX2_FAST(cpu_flags)) + dsp->compute_weights_line = ff_compute_weights_line_avx2; +} diff --git a/libavformat/4xm.c b/libavformat/4xm.c index f918b1fc57..e307560014 100644 --- a/libavformat/4xm.c +++ b/libavformat/4xm.c @@ -137,7 +137,8 @@ static int parse_strk(AVFormatContext *s, return AVERROR_INVALIDDATA; track = AV_RL32(buf + 8); - if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) { + if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1 || + track >= s->max_streams) { av_log(s, AV_LOG_ERROR, "current_track too large\n"); return AVERROR_INVALIDDATA; } @@ -148,6 +149,9 @@ static int parse_strk(AVFormatContext *s, memset(&fourxm->tracks[fourxm->track_count], 0, sizeof(AudioTrack) * (track + 1 - fourxm->track_count)); fourxm->track_count = track + 1; + } else { + if (fourxm->tracks[track].bits) + return AVERROR_INVALIDDATA; } fourxm->tracks[track].adpcm = AV_RL32(buf + 12); fourxm->tracks[track].channels = AV_RL32(buf + 36); diff --git a/libavformat/Makefile b/libavformat/Makefile index 3d6c8ef8f5..3dc6a479cc 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -61,7 +61,6 @@ OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtpdec_vp9.o \ rtpdec_xiph.o OBJS-$(CONFIG_RTPENC_CHAIN) += rtpenc_chain.o rtp.o -OBJS-$(CONFIG_SHARED) += log2_tab.o golomb_tab.o OBJS-$(CONFIG_SRTP) += srtp.o # muxers/demuxers @@ -88,11 +87,11 @@ OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o aiff.o pcm.o \ OBJS-$(CONFIG_AIFF_MUXER) += aiffenc.o aiff.o id3v2enc.o OBJS-$(CONFIG_AIX_DEMUXER) += aixdec.o OBJS-$(CONFIG_ALP_DEMUXER) += alp.o -OBJS-$(CONFIG_ALP_MUXER) += alp.o -OBJS-$(CONFIG_AMR_DEMUXER) += amr.o +OBJS-$(CONFIG_ALP_MUXER) += alp.o rawenc.o +OBJS-$(CONFIG_AMR_DEMUXER) += amr.o rawdec.o OBJS-$(CONFIG_AMR_MUXER) += amr.o rawenc.o -OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o -OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o +OBJS-$(CONFIG_AMRNB_DEMUXER) += amr.o rawdec.o +OBJS-$(CONFIG_AMRWB_DEMUXER) += amr.o rawdec.o OBJS-$(CONFIG_AMV_MUXER) += amvenc.o OBJS-$(CONFIG_ANM_DEMUXER) += anm.o OBJS-$(CONFIG_APC_DEMUXER) += apc.o @@ -138,6 +137,7 @@ OBJS-$(CONFIG_BINKA_DEMUXER) += binka.o OBJS-$(CONFIG_BINTEXT_DEMUXER) += bintext.o sauce.o OBJS-$(CONFIG_BIT_DEMUXER) += bit.o OBJS-$(CONFIG_BIT_MUXER) += bit.o +OBJS-$(CONFIG_BITPACKED_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o OBJS-$(CONFIG_BFSTM_DEMUXER) += brstm.o @@ -259,9 +259,11 @@ OBJS-$(CONFIG_IMAGE2PIPE_MUXER) += img2enc.o img2.o OBJS-$(CONFIG_IMAGE2_ALIAS_PIX_DEMUXER) += img2_alias_pix.o OBJS-$(CONFIG_IMAGE2_BRENDER_PIX_DEMUXER) += img2_brender_pix.o OBJS-$(CONFIG_IMAGE_BMP_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_CRI_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_DDS_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_DPX_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_EXR_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_GEM_PIPE_DEMUXER) += img2dec.o img2.o 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 @@ -271,7 +273,8 @@ OBJS-$(CONFIG_IMAGE_PBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_PCX_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_PHOTOCD_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMAGE_PGX_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 @@ -285,6 +288,7 @@ OBJS-$(CONFIG_IMAGE_WEBP_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XBM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XPM_PIPE_DEMUXER) += img2dec.o img2.o OBJS-$(CONFIG_IMAGE_XWD_PIPE_DEMUXER) += img2dec.o img2.o +OBJS-$(CONFIG_IMF_DEMUXER) += imfdec.o imf_cpl.o OBJS-$(CONFIG_INGENIENT_DEMUXER) += ingenientdec.o rawdec.o OBJS-$(CONFIG_IPMOVIE_DEMUXER) += ipmovie.o OBJS-$(CONFIG_IPU_DEMUXER) += ipudec.o rawdec.o @@ -314,11 +318,11 @@ OBJS-$(CONFIG_M4V_MUXER) += rawenc.o OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ flac_picture.o isom_tags.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ - qtpalette.o replaygain.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 \ flacenc_header.o avlanguage.o \ - vorbiscomment.o wv.o + vorbiscomment.o wv.o dovi_isom.o OBJS-$(CONFIG_MCA_DEMUXER) += mca.o OBJS-$(CONFIG_MCC_DEMUXER) += mccdec.o subtitles.o OBJS-$(CONFIG_MD5_MUXER) += hashenc.o @@ -337,10 +341,11 @@ OBJS-$(CONFIG_MMF_MUXER) += mmf.o rawenc.o OBJS-$(CONFIG_MODS_DEMUXER) += mods.o OBJS-$(CONFIG_MOFLEX_DEMUXER) += moflex.o OBJS-$(CONFIG_MOV_DEMUXER) += mov.o mov_chan.o mov_esds.o \ - qtpalette.o replaygain.o + qtpalette.o replaygain.o dovi_isom.o OBJS-$(CONFIG_MOV_MUXER) += movenc.o av1.o avc.o hevc.o vpcc.o \ movenchint.o mov_chan.o rtp.o \ - movenccenc.o movenc_ttml.o rawutils.o + movenccenc.o movenc_ttml.o rawutils.o \ + dovi_isom.o OBJS-$(CONFIG_MP2_MUXER) += rawenc.o OBJS-$(CONFIG_MP3_DEMUXER) += mp3dec.o replaygain.o OBJS-$(CONFIG_MP3_MUXER) += mp3enc.o rawenc.o id3v2enc.o @@ -482,6 +487,7 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_jpeg.o \ rtpenc_mpv.o \ rtpenc.o \ + rtpenc_rfc4175.o \ rtpenc_vc2hq.o \ rtpenc_vp8.o \ rtpenc_vp9.o \ @@ -500,6 +506,7 @@ 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_SCD_DEMUXER) += scd.o OBJS-$(CONFIG_SDP_DEMUXER) += rtsp.o OBJS-$(CONFIG_SDR2_DEMUXER) += sdr2.o OBJS-$(CONFIG_SDS_DEMUXER) += sdsdec.o @@ -556,8 +563,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 @@ -578,9 +585,7 @@ OBJS-$(CONFIG_WAV_DEMUXER) += wavdec.o pcm.o OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ - av1.o avc.o hevc.o isom_tags.o \ - flacenc_header.o avlanguage.o \ - wv.o vorbiscomment.o + av1.o avlanguage.o OBJS-$(CONFIG_WEBM_DASH_MANIFEST_MUXER) += webmdashenc.o OBJS-$(CONFIG_WEBM_CHUNK_MUXER) += webm_chunk.o OBJS-$(CONFIG_WEBP_MUXER) += webpenc.o @@ -663,7 +668,7 @@ OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o ip.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o # external library protocols -OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o +OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o urldecode.o OBJS-$(CONFIG_LIBRIST_PROTOCOL) += librist.o OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o @@ -675,12 +680,28 @@ OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o to_upper4.o +SHLIBOBJS-$(CONFIG_ISO_MEDIA) += mpegaudiotabs.o +SHLIBOBJS-$(CONFIG_FLV_MUXER) += mpeg4audio_sample_rates.o +SHLIBOBJS-$(CONFIG_HLS_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER) += mpeg4audio_sample_rates.o +SHLIBOBJS-$(CONFIG_MOV_DEMUXER) += ac3_channel_layout_tab.o +SHLIBOBJS-$(CONFIG_MP3_MUXER) += mpegaudiotabs.o +SHLIBOBJS-$(CONFIG_MXF_MUXER) += golomb_tab.o +SHLIBOBJS-$(CONFIG_NUT_MUXER) += mpegaudiotabs.o +SHLIBOBJS-$(CONFIG_RTPDEC) += jpegtables.o +SHLIBOBJS-$(CONFIG_RTP_MUXER) += golomb_tab.o jpegtables.o \ + mpeg4audio_sample_rates.o +SHLIBOBJS-$(CONFIG_SPDIF_MUXER) += dca_sample_rate_tab.o + # libavdevice dependencies OBJS-$(CONFIG_IEC61883_INDEV) += dv.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avformatres.o +SKIPHEADERS-$(CONFIG_IMF_DEMUXER) += imf.h SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h @@ -694,6 +715,7 @@ TESTPROGS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh TESTPROGS-$(CONFIG_MOV_MUXER) += movenc TESTPROGS-$(CONFIG_NETWORK) += noproxy TESTPROGS-$(CONFIG_SRTP) += srtp +TESTPROGS-$(CONFIG_IMF_DEMUXER) += imf TOOLS = aviocat \ ismindex \ diff --git a/libavformat/aadec.c b/libavformat/aadec.c index 72f4b6f7cc..b8a5428f1f 100644 --- a/libavformat/aadec.c +++ b/libavformat/aadec.c @@ -32,7 +32,6 @@ #include "libavutil/opt.h" #define AA_MAGIC 1469084982 /* this identifies an audible .aa file */ -#define MAX_CODEC_SECOND_SIZE 3982 #define MAX_TOC_ENTRIES 16 #define MAX_DICTIONARY_ENTRIES 128 #define TEA_BLOCK_SIZE 8 @@ -72,18 +71,18 @@ static int get_second_size(char *codec_name) static int aa_read_header(AVFormatContext *s) { - int i, j, idx, largest_idx = -1; + int largest_idx = -1; uint32_t toc_size, npairs, header_seed = 0, start; char codec_name[64] = {0}; - uint8_t output[24], dst[8], src[8]; + uint8_t buf[24]; int64_t largest_size = -1, current_size = -1, chapter_pos; struct toc_entry { uint32_t offset; uint32_t size; } TOC[MAX_TOC_ENTRIES]; - uint32_t header_key_part[4]; uint8_t header_key[16] = {0}; AADemuxContext *c = s->priv_data; + char file_key[2 * sizeof(c->file_key) + 1]; AVIOContext *pb = s->pb; AVStream *st; FFStream *sti; @@ -96,7 +95,7 @@ static int aa_read_header(AVFormatContext *s) avio_skip(pb, 4); // unidentified integer if (toc_size > MAX_TOC_ENTRIES || toc_size < 2) return AVERROR_INVALIDDATA; - for (i = 0; i < toc_size; i++) { // read TOC + for (uint32_t i = 0; i < toc_size; i++) { // read TOC avio_skip(pb, 4); // TOC entry index TOC[i].offset = avio_rb32(pb); // block offset TOC[i].size = avio_rb32(pb); // block size @@ -105,7 +104,7 @@ static int aa_read_header(AVFormatContext *s) npairs = avio_rb32(pb); // read dictionary entries if (npairs > MAX_DICTIONARY_ENTRIES) return AVERROR_INVALIDDATA; - for (i = 0; i < npairs; i++) { + for (uint32_t i = 0; i < npairs; i++) { char key[128], val[128]; uint32_t nkey, nval; @@ -121,6 +120,7 @@ static int aa_read_header(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "HeaderSeed is <%s>\n", val); header_seed = atoi(val); } else if (!strcmp(key, "HeaderKey")) { // this looks like "1234567890 1234567890 1234567890 1234567890" + uint32_t header_key_part[4]; av_log(s, AV_LOG_DEBUG, "HeaderKey is <%s>\n", val); ret = sscanf(val, "%"SCNu32"%"SCNu32"%"SCNu32"%"SCNu32, @@ -128,13 +128,10 @@ static int aa_read_header(AVFormatContext *s) if (ret != 4) return AVERROR_INVALIDDATA; - for (idx = 0; idx < 4; idx++) { + for (int idx = 0; idx < 4; idx++) AV_WB32(&header_key[idx * 4], header_key_part[idx]); // convert each part to BE! - } - av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is "); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_DEBUG, "%02x", header_key[i]); - av_log(s, AV_LOG_DEBUG, "\n"); + ff_data_to_hex(key, header_key, sizeof(header_key), 1); + av_log(s, AV_LOG_DEBUG, "Processed HeaderKey is %s\n", key); } else { av_dict_set(&s->metadata, key, val, 0); } @@ -157,23 +154,14 @@ static int aa_read_header(AVFormatContext *s) if (!c->tea_ctx) return AVERROR(ENOMEM); av_tea_init(c->tea_ctx, c->aa_fixed_key, 16); - output[0] = output[1] = 0; // purely for padding purposes - memcpy(output + 2, header_key, 16); - idx = 0; - for (i = 0; i < 3; i++) { // TEA CBC with weird mixed endianness - AV_WB32(src, header_seed); - AV_WB32(src + 4, header_seed + 1); - header_seed += 2; - av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 0); // TEA ECB encrypt - for (j = 0; j < TEA_BLOCK_SIZE && idx < 18; j+=1, idx+=1) { - output[idx] = output[idx] ^ dst[j]; - } - } - memcpy(c->file_key, output + 2, 16); // skip first 2 bytes of output - av_log(s, AV_LOG_DEBUG, "File key is "); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_DEBUG, "%02x", c->file_key[i]); - av_log(s, AV_LOG_DEBUG, "\n"); + for (int i = 0; i < 6; i++) + AV_WB32(buf + 4 * i, header_seed + i); + av_tea_crypt(c->tea_ctx, buf, buf, 3, NULL, 0); + AV_WN64(c->file_key, AV_RN64(buf + 2) ^ AV_RN64(header_key)); + AV_WN64(c->file_key + 8, AV_RN64(buf + 10) ^ AV_RN64(header_key + 8)); + ff_data_to_hex(file_key, c->file_key, sizeof(c->file_key), 1); + av_log(s, AV_LOG_DEBUG, "File key is %s\n", file_key); + av_tea_init(c->tea_ctx, c->file_key, 16); /* decoder setup */ st = avformat_new_stream(s, NULL); @@ -206,7 +194,7 @@ static int aa_read_header(AVFormatContext *s) } /* determine, and jump to audio start offset */ - for (i = 1; i < toc_size; i++) { // skip the first entry! + for (uint32_t i = 1; i < toc_size; i++) { // skip the first entry! current_size = TOC[i].size; if (current_size > largest_size) { largest_idx = i; @@ -247,13 +235,6 @@ static int aa_read_header(AVFormatContext *s) static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) { - uint8_t dst[TEA_BLOCK_SIZE]; - uint8_t src[TEA_BLOCK_SIZE]; - int i; - int trailing_bytes; - int blocks; - uint8_t buf[MAX_CODEC_SECOND_SIZE * 2]; - int written = 0; int ret; AADemuxContext *c = s->priv_data; uint64_t pos = avio_tell(s->pb); @@ -272,7 +253,6 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_DEBUG, "Chapter %d (%" PRId64 " bytes)\n", c->chapter_idx, c->current_chapter_size); c->chapter_idx = c->chapter_idx + 1; avio_skip(s->pb, 4); // data start offset - pos += 8; c->current_codec_second_size = c->codec_second_size; } @@ -281,41 +261,26 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt) c->current_codec_second_size = c->current_chapter_size % c->current_codec_second_size; } - // decrypt c->current_codec_second_size bytes - blocks = c->current_codec_second_size / TEA_BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - ret = avio_read(s->pb, src, TEA_BLOCK_SIZE); - if (ret != TEA_BLOCK_SIZE) - return (ret < 0) ? ret : AVERROR_EOF; - av_tea_init(c->tea_ctx, c->file_key, 16); - av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1); - memcpy(buf + written, dst, TEA_BLOCK_SIZE); - written = written + TEA_BLOCK_SIZE; - } - trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE; - if (trailing_bytes != 0) { // trailing bytes are left unencrypted! - ret = avio_read(s->pb, src, trailing_bytes); - if (ret != trailing_bytes) - return (ret < 0) ? ret : AVERROR_EOF; - memcpy(buf + written, src, trailing_bytes); - written = written + trailing_bytes; - } + ret = av_get_packet(s->pb, pkt, c->current_codec_second_size); + if (ret != c->current_codec_second_size) + return AVERROR_EOF; + + // decrypt c->current_codec_second_size bytes in blocks of TEA_BLOCK_SIZE + // trailing bytes are left unencrypted! + av_tea_crypt(c->tea_ctx, pkt->data, pkt->data, + c->current_codec_second_size / TEA_BLOCK_SIZE, NULL, 1); // update state c->current_chapter_size = c->current_chapter_size - c->current_codec_second_size; if (c->current_chapter_size <= 0) c->current_chapter_size = 0; - if (c->seek_offset > written) + if (c->seek_offset > c->current_codec_second_size) c->seek_offset = 0; // ignore wrong estimate - - ret = av_new_packet(pkt, written - c->seek_offset); - if (ret < 0) - return ret; - memcpy(pkt->data, buf + c->seek_offset, written - c->seek_offset); - pkt->pos = pos; - + pkt->data += c->seek_offset; + pkt->size -= c->seek_offset; c->seek_offset = 0; + return 0; } diff --git a/libavformat/ac3_channel_layout_tab.c b/libavformat/ac3_channel_layout_tab.c new file mode 100644 index 0000000000..cba198ccc5 --- /dev/null +++ b/libavformat/ac3_channel_layout_tab.c @@ -0,0 +1,22 @@ +/* + * AC-3 channel layout table + * copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/ac3_channel_layout_tab.h" diff --git a/libavformat/aiffdec.c b/libavformat/aiffdec.c index a826bc998a..7afadeb085 100644 --- a/libavformat/aiffdec.c +++ b/libavformat/aiffdec.c @@ -120,6 +120,9 @@ static int get_aiff_header(AVFormatContext *s, int size, sample_rate = val << exp; else sample_rate = (val + (1ULL<<(-exp-1))) >> -exp; + if (sample_rate <= 0) + return AVERROR_INVALIDDATA; + par->sample_rate = sample_rate; if (size < 18) return AVERROR_INVALIDDATA; @@ -182,8 +185,10 @@ static int get_aiff_header(AVFormatContext *s, int size, par->block_align = (av_get_bits_per_sample(par->codec_id) * par->channels) >> 3; if (aiff->block_duration) { - par->bit_rate = (int64_t)par->sample_rate * (par->block_align << 3) / - aiff->block_duration; + par->bit_rate = av_rescale(par->sample_rate, par->block_align * 8LL, + aiff->block_duration); + if (par->bit_rate < 0) + par->bit_rate = 0; } /* Chunk is over */ @@ -305,7 +310,7 @@ static int aiff_read_header(AVFormatContext *s) break; case MKTAG('w', 'a', 'v', 'e'): if ((uint64_t)size > (1<<30)) - return -1; + return AVERROR_INVALIDDATA; if ((ret = ff_get_extradata(s, st->codecpar, pb, size)) < 0) return ret; if ( (st->codecpar->codec_id == AV_CODEC_ID_QDMC || st->codecpar->codec_id == AV_CODEC_ID_QDM2) @@ -365,9 +370,9 @@ got_sound: if (!st->codecpar->block_align && st->codecpar->codec_id == AV_CODEC_ID_QCELP) { av_log(s, AV_LOG_WARNING, "qcelp without wave chunk, assuming full rate\n"); st->codecpar->block_align = 35; - } else if (!st->codecpar->block_align) { + } else if (st->codecpar->block_align <= 0) { av_log(s, AV_LOG_ERROR, "could not find COMM tag or invalid block_align value\n"); - return -1; + return AVERROR_INVALIDDATA; } /* Now positioned, get the sound data start and end */ diff --git a/libavformat/aiffenc.c b/libavformat/aiffenc.c index 24bc17400e..1fd6b8a70b 100644 --- a/libavformat/aiffenc.c +++ b/libavformat/aiffenc.c @@ -37,7 +37,7 @@ typedef struct AIFFOutputContext { int64_t frames; int64_t ssnd; int audio_stream_idx; - PacketList *pict_list, *pict_list_end; + PacketList pict_list; int write_id3v2; int id3v2_version; } AIFFOutputContext; @@ -48,9 +48,9 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) uint64_t pos, end, size; ID3v2EncContext id3v2 = { 0 }; AVIOContext *pb = s->pb; - PacketList *pict_list = aiff->pict_list; + PacketListEntry *list_entry = aiff->pict_list.head; - if (!s->metadata && !s->nb_chapters && !aiff->pict_list) + if (!s->metadata && !s->nb_chapters && !list_entry) return 0; avio_wl32(pb, MKTAG('I', 'D', '3', ' ')); @@ -59,10 +59,10 @@ static int put_id3v2_tags(AVFormatContext *s, AIFFOutputContext *aiff) ff_id3v2_start(&id3v2, pb, aiff->id3v2_version, ID3v2_DEFAULT_MAGIC); ff_id3v2_write_metadata(s, &id3v2); - while (pict_list) { - if ((ret = ff_id3v2_write_apic(s, &id3v2, &pict_list->pkt)) < 0) + while (list_entry) { + if ((ret = ff_id3v2_write_apic(s, &id3v2, &list_entry->pkt)) < 0) return ret; - pict_list = pict_list->next; + list_entry = list_entry->next; } ff_id3v2_finish(&id3v2, pb, s->metadata_header_padding); @@ -218,8 +218,7 @@ static int aiff_write_packet(AVFormatContext *s, AVPacket *pkt) if (s->streams[pkt->stream_index]->nb_frames >= 1) return 0; - return avpriv_packet_list_put(&aiff->pict_list, &aiff->pict_list_end, - pkt, av_packet_ref, 0); + return avpriv_packet_list_put(&aiff->pict_list, pkt, NULL, 0); } return 0; @@ -265,7 +264,7 @@ static void aiff_deinit(AVFormatContext *s) { AIFFOutputContext *aiff = s->priv_data; - avpriv_packet_list_free(&aiff->pict_list, &aiff->pict_list_end); + avpriv_packet_list_free(&aiff->pict_list); } #define OFFSET(x) offsetof(AIFFOutputContext, x) diff --git a/libavformat/allformats.c b/libavformat/allformats.c index cbfadcb639..d066a7745b 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -96,6 +96,7 @@ extern const AVInputFormat ff_bink_demuxer; extern const AVInputFormat ff_binka_demuxer; extern const AVInputFormat ff_bit_demuxer; extern const AVOutputFormat ff_bit_muxer; +extern const AVInputFormat ff_bitpacked_demuxer; extern const AVInputFormat ff_bmv_demuxer; extern const AVInputFormat ff_bfstm_demuxer; extern const AVInputFormat ff_brstm_demuxer; @@ -212,6 +213,7 @@ extern const AVInputFormat ff_image2pipe_demuxer; extern const AVOutputFormat ff_image2pipe_muxer; extern const AVInputFormat ff_image2_alias_pix_demuxer; extern const AVInputFormat ff_image2_brender_pix_demuxer; +extern const AVInputFormat ff_imf_demuxer; extern const AVInputFormat ff_ingenient_demuxer; extern const AVInputFormat ff_ipmovie_demuxer; extern const AVOutputFormat ff_ipod_muxer; @@ -392,6 +394,7 @@ extern const AVOutputFormat ff_sbc_muxer; extern const AVInputFormat ff_sbg_demuxer; extern const AVInputFormat ff_scc_demuxer; extern const AVOutputFormat ff_scc_muxer; +extern const AVInputFormat ff_scd_demuxer; extern const AVInputFormat ff_sdp_demuxer; extern const AVInputFormat ff_sdr2_demuxer; extern const AVInputFormat ff_sds_demuxer; diff --git a/libavformat/amr.c b/libavformat/amr.c index 0a044d69af..bc22c2f84f 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -53,12 +53,10 @@ static int amr_write_header(AVFormatContext *s) AVIOContext *pb = s->pb; AVCodecParameters *par = s->streams[0]->codecpar; - s->priv_data = NULL; - if (par->codec_id == AV_CODEC_ID_AMR_NB) { - avio_write(pb, AMR_header, sizeof(AMR_header) - 1); /* magic number */ + avio_write(pb, AMR_header, sizeof(AMR_header)); /* magic number */ } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { - avio_write(pb, AMRWB_header, sizeof(AMRWB_header) - 1); /* magic number */ + avio_write(pb, AMRWB_header, sizeof(AMRWB_header)); /* magic number */ } else { return -1; } @@ -66,6 +64,7 @@ static int amr_write_header(AVFormatContext *s) } #endif /* CONFIG_AMR_MUXER */ +#if CONFIG_AMR_DEMUXER static int amr_probe(const AVProbeData *p) { // Only check for "#!AMR" which could be amr-wb, amr-nb. @@ -92,7 +91,7 @@ static int amr_read_header(AVFormatContext *s) read = avio_read(pb, header, sizeof(header)); if (read < 0) - return ret; + return read; st = avformat_new_stream(s, NULL); if (!st) @@ -140,7 +139,6 @@ static int amr_read_header(AVFormatContext *s) return 0; } -#if CONFIG_AMR_DEMUXER const AVInputFormat ff_amr_demuxer = { .name = "amr", .long_name = NULL_IF_CONFIG_SMALL("3GPP AMR"), diff --git a/libavformat/apngenc.c b/libavformat/apngenc.c index c97c475274..767074ecf3 100644 --- a/libavformat/apngenc.c +++ b/libavformat/apngenc.c @@ -91,9 +91,9 @@ static int apng_write_header(AVFormatContext *format_context) return AVERROR(EINVAL); } - if (apng->last_delay.num > USHRT_MAX || apng->last_delay.den > USHRT_MAX) { + if (apng->last_delay.num > UINT16_MAX || apng->last_delay.den > UINT16_MAX) { av_reduce(&apng->last_delay.num, &apng->last_delay.den, - apng->last_delay.num, apng->last_delay.den, USHRT_MAX); + apng->last_delay.num, apng->last_delay.den, UINT16_MAX); av_log(format_context, AV_LOG_WARNING, "Last frame delay is too precise. Reducing to %d/%d (%f).\n", apng->last_delay.num, apng->last_delay.den, (double)apng->last_delay.num / apng->last_delay.den); @@ -191,7 +191,7 @@ static int flush_packet(AVFormatContext *format_context, AVPacket *packet) 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; - if (!av_reduce(&delay.num, &delay.den, delay_num_raw, delay_den_raw, USHRT_MAX) && + if (!av_reduce(&delay.num, &delay.den, delay_num_raw, delay_den_raw, UINT16_MAX) && !apng->framerate_warned) { av_log(format_context, AV_LOG_WARNING, "Frame rate is too high or specified too precisely. Unable to copy losslessly.\n"); @@ -281,9 +281,9 @@ static void apng_deinit(AVFormatContext *s) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { { "plays", "Number of times to play the output: 0 - infinite loop, 1 - no loop", OFFSET(plays), - AV_OPT_TYPE_INT, { .i64 = 1 }, 0, UINT_MAX, ENC }, + AV_OPT_TYPE_INT, { .i64 = 1 }, 0, UINT16_MAX, ENC }, { "final_delay", "Force delay after the last frame", OFFSET(last_delay), - AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, USHRT_MAX, ENC }, + AV_OPT_TYPE_RATIONAL, { .dbl = 0 }, 0, UINT16_MAX, ENC }, { NULL }, }; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index a2af7e9f89..6ce367e854 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -322,6 +322,7 @@ #include "libavformat/version.h" struct AVFormatContext; +struct AVStream; struct AVDeviceInfoList; struct AVDeviceCapabilitiesQuery; @@ -462,6 +463,13 @@ typedef struct AVProbeData { /// Demuxer will use avio_open, no opened file should be provided by the caller. #define AVFMT_NOFILE 0x0001 #define AVFMT_NEEDNUMBER 0x0002 /**< Needs '%d' in filename. */ +/** + * The muxer/demuxer is experimental and should be used with caution. + * + * - demuxers: will not be selected automatically by probing, must be specified + * explicitly. + */ +#define AVFMT_EXPERIMENTAL 0x0004 #define AVFMT_SHOW_IDS 0x0008 /**< Show format stream IDs numbers. */ #define AVFMT_GLOBALHEADER 0x0040 /**< Format wants global header. */ #define AVFMT_NOTIMESTAMPS 0x0080 /**< Format does not need / have any timestamps. */ @@ -623,9 +631,13 @@ typedef struct AVOutputFormat { /** * Set up any necessary bitstream filtering and extract any extra data needed * for the global header. + * + * @note pkt might have been directly forwarded by a meta-muxer; therefore + * pkt->stream_index as well as the pkt's timebase might be invalid. * Return 0 if more packets from this stream must be checked; 1 if not. */ - int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt); + int (*check_bitstream)(struct AVFormatContext *s, struct AVStream *st, + const AVPacket *pkt); } AVOutputFormat; /** * @} @@ -803,22 +815,56 @@ typedef struct AVIndexEntry { int min_distance; /**< Minimum distance between this and the previous keyframe, used to avoid unneeded searching. */ } AVIndexEntry; -#define AV_DISPOSITION_DEFAULT 0x0001 -#define AV_DISPOSITION_DUB 0x0002 -#define AV_DISPOSITION_ORIGINAL 0x0004 -#define AV_DISPOSITION_COMMENT 0x0008 -#define AV_DISPOSITION_LYRICS 0x0010 -#define AV_DISPOSITION_KARAOKE 0x0020 +/** + * The stream should be chosen by default among other streams of the same type, + * unless the user has explicitly specified otherwise. + */ +#define AV_DISPOSITION_DEFAULT (1 << 0) +/** + * The stream is not in original language. + * + * @note AV_DISPOSITION_ORIGINAL is the inverse of this disposition. At most + * one of them should be set in properly tagged streams. + * @note This disposition may apply to any stream type, not just audio. + */ +#define AV_DISPOSITION_DUB (1 << 1) +/** + * The stream is in original language. + * + * @see the notes for AV_DISPOSITION_DUB + */ +#define AV_DISPOSITION_ORIGINAL (1 << 2) +/** + * The stream is a commentary track. + */ +#define AV_DISPOSITION_COMMENT (1 << 3) +/** + * The stream contains song lyrics. + */ +#define AV_DISPOSITION_LYRICS (1 << 4) +/** + * The stream contains karaoke audio. + */ +#define AV_DISPOSITION_KARAOKE (1 << 5) /** * Track should be used during playback by default. * Useful for subtitle track that should be displayed * even when user did not explicitly ask for subtitles. */ -#define AV_DISPOSITION_FORCED 0x0040 -#define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ -#define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ -#define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ +#define AV_DISPOSITION_FORCED (1 << 6) +/** + * The stream is intended for hearing impaired audiences. + */ +#define AV_DISPOSITION_HEARING_IMPAIRED (1 << 7) +/** + * The stream is intended for visually impaired audiences. + */ +#define AV_DISPOSITION_VISUAL_IMPAIRED (1 << 8) +/** + * The audio stream contains music and sound effects without voice. + */ +#define AV_DISPOSITION_CLEAN_EFFECTS (1 << 9) /** * The stream is stored in the file as an attached picture/"cover art" (e.g. * APIC frame in ID3v2). The first (usually only) packet associated with it @@ -826,21 +872,53 @@ typedef struct AVIndexEntry { * seeking takes place. It can also be accessed at any time in * AVStream.attached_pic. */ -#define AV_DISPOSITION_ATTACHED_PIC 0x0400 +#define AV_DISPOSITION_ATTACHED_PIC (1 << 10) /** * The stream is sparse, and contains thumbnail images, often corresponding * to chapter markers. Only ever used with AV_DISPOSITION_ATTACHED_PIC. */ -#define AV_DISPOSITION_TIMED_THUMBNAILS 0x0800 +#define AV_DISPOSITION_TIMED_THUMBNAILS (1 << 11) /** - * To specify text track kind (different from subtitles default). + * The subtitle stream contains captions, providing a transcription and possibly + * a translation of audio. Typically intended for hearing-impaired audiences. */ -#define AV_DISPOSITION_CAPTIONS 0x10000 -#define AV_DISPOSITION_DESCRIPTIONS 0x20000 -#define AV_DISPOSITION_METADATA 0x40000 -#define AV_DISPOSITION_DEPENDENT 0x80000 ///< dependent audio stream (mix_type=0 in mpegts) -#define AV_DISPOSITION_STILL_IMAGE 0x100000 ///< still images in video stream (still_picture_flag=1 in mpegts) +#define AV_DISPOSITION_CAPTIONS (1 << 16) +/** + * The subtitle stream contains a textual description of the video content. + * Typically intended for visually-impaired audiences or for the cases where the + * video cannot be seen. + */ +#define AV_DISPOSITION_DESCRIPTIONS (1 << 17) +/** + * The subtitle stream contains time-aligned metadata that is not intended to be + * directly presented to the user. + */ +#define AV_DISPOSITION_METADATA (1 << 18) +/** + * The audio stream is intended to be mixed with another stream before + * presentation. + * Corresponds to mix_type=0 in mpegts. + */ +#define AV_DISPOSITION_DEPENDENT (1 << 19) +/** + * The video stream contains still images. + */ +#define AV_DISPOSITION_STILL_IMAGE (1 << 20) + +/** + * @return The AV_DISPOSITION_* flag corresponding to disp or a negative error + * code if disp does not correspond to a known stream disposition. + */ +int av_disposition_from_string(const char *disp); + +/** + * @param disposition a combination of AV_DISPOSITION_* values + * @return The string description corresponding to the lowest set bit in + * disposition. NULL when the lowest set bit does not correspond + * to a known disposition or when disposition is 0. + */ +const char *av_disposition_to_string(int disposition); /** * Options for behavior on timestamp wrap detection. @@ -857,6 +935,13 @@ typedef struct AVIndexEntry { * sizeof(AVStream) must not be used outside libav*. */ typedef struct AVStream { +#if FF_API_AVSTREAM_CLASS + /** + * A class for @ref avoptions. Set on stream creation. + */ + const AVClass *av_class; +#endif + int index; /**< stream index in AVFormatContext */ /** * Format-specific stream ID. @@ -903,7 +988,13 @@ typedef struct AVStream { int64_t nb_frames; ///< number of frames in this stream if known or 0 - int disposition; /**< AV_DISPOSITION_* bit field */ + /** + * Stream disposition - a combination of AV_DISPOSITION_* flags. + * - demuxing: set by libavformat when creating the stream or in + * avformat_find_stream_info(). + * - muxing: may be set by the caller before avformat_write_header(). + */ + int disposition; enum AVDiscard discard; ///< Selects which packets can be discarded at will and do not need to be demuxed. @@ -1702,6 +1793,19 @@ typedef struct AVFormatContext { * - decoding: set by user */ int max_probe_packets; + + /** + * A callback for closing the streams opened with AVFormatContext.io_open(). + * + * Using this is preferred over io_close, because this can return an error. + * Therefore this callback is used instead of io_close by the generic + * libavformat code if io_close is NULL or the default. + * + * @param s the format context + * @param pb IO context to be closed and freed + * @return 0 on success, a negative AVERROR code on failure + */ + int (*io_close2)(struct AVFormatContext *s, AVIOContext *pb); } AVFormatContext; /** @@ -1806,6 +1910,14 @@ void avformat_free_context(AVFormatContext *s); */ const AVClass *avformat_get_class(void); +/** + * Get the AVClass for AVStream. It can be used in combination with + * AV_OPT_SEARCH_FAKE_OBJ for examining options. + * + * @see av_opt_find(). + */ +const AVClass *av_stream_get_class(void); + /** * Add a new stream to a media file. * diff --git a/libavformat/avidec.c b/libavformat/avidec.c index b10c3efa61..86f857b1e3 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -240,6 +240,8 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) } else { int64_t offset, pos; int duration; + int ret; + offset = avio_rl64(pb); avio_rl32(pb); /* size */ duration = avio_rl32(pb); @@ -257,7 +259,7 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) if (avio_seek(pb, offset + 8, SEEK_SET) < 0) return -1; avi->odml_depth++; - read_odml_index(s, frame_num); + ret = read_odml_index(s, frame_num); avi->odml_depth--; frame_num += duration; @@ -265,7 +267,8 @@ static int read_odml_index(AVFormatContext *s, int64_t frame_num) av_log(s, AV_LOG_ERROR, "Failed to restore position after reading index\n"); return -1; } - + if (ret < 0) + return ret; } } avi->index_loaded = 2; diff --git a/libavformat/avienc.c b/libavformat/avienc.c index 3fbde0be1e..be2493ce55 100644 --- a/libavformat/avienc.c +++ b/libavformat/avienc.c @@ -448,7 +448,7 @@ static int avi_write_header(AVFormatContext *s) par->bits_per_coded_sample = 16; avist->pal_offset = avio_tell(pb) + 40; ff_put_bmp_header(pb, par, 0, 0, avi->flipped_raw_rgb); - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_avi, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_AVI, par->bits_per_coded_sample); if ( !par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO diff --git a/libavformat/avio.h b/libavformat/avio.h index a7b56ab667..cd63322a62 100644 --- a/libavformat/avio.h +++ b/libavformat/avio.h @@ -290,13 +290,31 @@ typedef struct AVIOContext { */ int ignore_boundary_point; +#if FF_API_AVIOCONTEXT_WRITTEN + /** + * @deprecated field utilized privately by libavformat. For a public + * statistic of how many bytes were written out, see + * AVIOContext::bytes_written. + */ + attribute_deprecated int64_t written; +#endif /** * Maximum reached position before a backward seek in the write buffer, * used keeping track of already written data for a later flush. */ unsigned char *buf_ptr_max; + + /** + * Read-only statistic of bytes read for this AVIOContext. + */ + int64_t bytes_read; + + /** + * Read-only statistic of bytes written for this AVIOContext. + */ + int64_t bytes_written; } AVIOContext; /** diff --git a/libavformat/avio_internal.h b/libavformat/avio_internal.h index eded38759b..1f5e3d474b 100644 --- a/libavformat/avio_internal.h +++ b/libavformat/avio_internal.h @@ -51,6 +51,11 @@ typedef struct FFIOContext { */ int64_t bytes_read; + /** + * Bytes written statistic + */ + int64_t bytes_written; + /** * seek statistic */ @@ -66,6 +71,12 @@ typedef struct FFIOContext { * used after probing to ensure seekback and to reset the buffer size */ int orig_buffer_size; + + /** + * Written output size + * is updated each time a successful writeout ends up further position-wise + */ + int64_t written_output_size; } FFIOContext; static av_always_inline FFIOContext *ffiocontext(AVIOContext *ctx) @@ -195,6 +206,12 @@ int ffio_fdopen(AVIOContext **s, URLContext *h); */ URLContext *ffio_geturlcontext(AVIOContext *s); + +/** + * Read url related dictionary options from the AVIOContext and write to the given dictionary + */ +int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts); + /** * Open a write-only fake memory stream. The written data is not stored * anywhere - this is only used for measuring the amount of data diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3d87d66091..29d4bd7510 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -22,6 +22,7 @@ #include "libavutil/bprint.h" #include "libavutil/crc.h" #include "libavutil/dict.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -124,7 +125,11 @@ void ffio_init_context(FFIOContext *ctx, ctx->current_type = AVIO_DATA_MARKER_UNKNOWN; ctx->last_time = AV_NOPTS_VALUE; ctx->short_seek_get = NULL; +#if FF_API_AVIOCONTEXT_WRITTEN +FF_DISABLE_DEPRECATION_WARNINGS s->written = 0; +FF_ENABLE_DEPRECATION_WARNINGS +#endif } AVIOContext *avio_alloc_context( @@ -164,8 +169,17 @@ static void writeout(AVIOContext *s, const uint8_t *data, int len) if (ret < 0) { s->error = ret; } else { - if (s->pos + len > s->written) - s->written = s->pos + len; + ctx->bytes_written += len; + s->bytes_written = ctx->bytes_written; + + if (s->pos + len > ctx->written_output_size) { + ctx->written_output_size = s->pos + len; +#if FF_API_AVIOCONTEXT_WRITTEN +FF_DISABLE_DEPRECATION_WARNINGS + s->written = ctx->written_output_size; +FF_ENABLE_DEPRECATION_WARNINGS +#endif + } } } if (ctx->current_type == AVIO_DATA_MARKER_SYNC_POINT || @@ -337,13 +351,14 @@ int64_t avio_skip(AVIOContext *s, int64_t offset) int64_t avio_size(AVIOContext *s) { + FFIOContext *const ctx = ffiocontext(s); int64_t size; if (!s) return AVERROR(EINVAL); - if (s->written) - return s->written; + if (ctx->written_output_size) + return ctx->written_output_size; if (!s->seek) return AVERROR(ENOSYS); @@ -572,6 +587,7 @@ static void fill_buffer(AVIOContext *s) s->buf_ptr = dst; s->buf_end = dst + len; ffiocontext(s)->bytes_read += len; + s->bytes_read = ffiocontext(s)->bytes_read; } } @@ -630,7 +646,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) while (size > 0) { len = FFMIN(s->buf_end - s->buf_ptr, size); if (len == 0 || s->write_flag) { - if((s->direct || size > s->buffer_size) && !s->update_checksum) { + if((s->direct || size > s->buffer_size) && !s->update_checksum && s->read_packet) { // bypass the buffer and read data directly into buf len = read_packet_wrapper(s, buf, size); if (len == AVERROR_EOF) { @@ -645,6 +661,7 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) } else { s->pos += len; ffiocontext(s)->bytes_read += len; + s->bytes_read = ffiocontext(s)->bytes_read; size -= len; buf += len; // reset the buffer @@ -960,18 +977,19 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) (int (*)(void *, uint8_t *, int)) ffurl_read, (int (*)(void *, uint8_t *, int)) ffurl_write, (int64_t (*)(void *, int64_t, int))ffurl_seek); - if (!*s) - goto fail; - + if (!*s) { + av_freep(&buffer); + return AVERROR(ENOMEM); + } (*s)->protocol_whitelist = av_strdup(h->protocol_whitelist); if (!(*s)->protocol_whitelist && h->protocol_whitelist) { avio_closep(s); - goto fail; + return AVERROR(ENOMEM); } (*s)->protocol_blacklist = av_strdup(h->protocol_blacklist); if (!(*s)->protocol_blacklist && h->protocol_blacklist) { avio_closep(s); - goto fail; + return AVERROR(ENOMEM); } (*s)->direct = h->flags & AVIO_FLAG_DIRECT; @@ -989,9 +1007,6 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) ((FFIOContext*)(*s))->short_seek_get = (int (*)(void *))ffurl_get_short_seek; (*s)->av_class = &ff_avio_class; return 0; -fail: - av_freep(&buffer); - return AVERROR(ENOMEM); } URLContext* ffio_geturlcontext(AVIOContext *s) @@ -1005,6 +1020,30 @@ URLContext* ffio_geturlcontext(AVIOContext *s) return NULL; } +int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts) +{ + const char *opts[] = { + "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL }; + const char **opt = opts; + uint8_t *buf = NULL; + int ret = 0; + + while (*opt) { + if (av_opt_get(pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { + if (buf[0] != '\0') { + ret = av_dict_set(avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); + if (ret < 0) + return ret; + } else { + av_freep(&buf); + } + } + opt++; + } + + return ret; +} + static void update_checksum(AVIOContext *s) { if (s->update_checksum && s->buf_ptr > s->checksum_ptr) { @@ -1214,6 +1253,7 @@ int avio_close(AVIOContext *s) { FFIOContext *const ctx = ffiocontext(s); URLContext *h; + int ret, error; if (!s) return 0; @@ -1224,16 +1264,22 @@ int avio_close(AVIOContext *s) av_freep(&s->buffer); if (s->write_flag) - av_log(s, AV_LOG_VERBOSE, "Statistics: %d seeks, %d writeouts\n", - ctx->seek_count, ctx->writeout_count); + av_log(s, AV_LOG_VERBOSE, + "Statistics: %"PRId64" bytes written, %d seeks, %d writeouts\n", + ctx->bytes_written, ctx->seek_count, ctx->writeout_count); else av_log(s, AV_LOG_VERBOSE, "Statistics: %"PRId64" bytes read, %d seeks\n", ctx->bytes_read, ctx->seek_count); av_opt_free(s); + error = s->error; avio_context_free(&s); - return ffurl_close(h); + ret = ffurl_close(h); + if (ret < 0) + return ret; + + return error; } int avio_closep(AVIOContext **s) diff --git a/libavformat/cafdec.c b/libavformat/cafdec.c index 3ff0558afe..4b5b15b58d 100644 --- a/libavformat/cafdec.c +++ b/libavformat/cafdec.c @@ -224,7 +224,7 @@ static int read_pakt_chunk(AVFormatContext *s, int64_t size) av_log(s, AV_LOG_ERROR, "error reading packet table\n"); return AVERROR_INVALIDDATA; } - avio_skip(pb, ccount + size - avio_tell(pb)); + avio_seek(pb, ccount + size, SEEK_SET); caf->num_bytes = pos; return 0; @@ -331,7 +331,7 @@ static int read_header(AVFormatContext *s) if (size > 0 && (pb->seekable & AVIO_SEEKABLE_NORMAL)) { if (pos > INT64_MAX - size) return AVERROR_INVALIDDATA; - avio_skip(pb, FFMAX(0, pos + size - avio_tell(pb))); + avio_seek(pb, pos + size, SEEK_SET); } } diff --git a/libavformat/cinedec.c b/libavformat/cinedec.c index c83a4c1471..f4779b2676 100644 --- a/libavformat/cinedec.c +++ b/libavformat/cinedec.c @@ -33,6 +33,7 @@ typedef struct { uint64_t pts; + uint64_t maxsize; } CineDemuxContext; /** Compression */ @@ -288,21 +289,32 @@ static int cine_read_packet(AVFormatContext *avctx, AVPacket *pkt) FFStream *const sti = ffstream(st); AVIOContext *pb = avctx->pb; int n, size, ret; + int64_t ret64; if (cine->pts >= sti->nb_index_entries) return AVERROR_EOF; - avio_seek(pb, sti->index_entries[cine->pts].pos, SEEK_SET); + ret64 = avio_seek(pb, sti->index_entries[cine->pts].pos, SEEK_SET); + if (ret64 < 0) + return ret64; n = avio_rl32(pb); if (n < 8) return AVERROR_INVALIDDATA; avio_skip(pb, n - 8); size = avio_rl32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; + + if (cine->maxsize && 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); if (ret < 0) return ret; + if (ret != size) + cine->maxsize = sti->index_entries[cine->pts].pos + n + ret; + pkt->pts = cine->pts++; pkt->stream_index = 0; pkt->flags |= AV_PKT_FLAG_KEY; diff --git a/libavformat/concat.c b/libavformat/concat.c index 2560811ff9..faeba2293a 100644 --- a/libavformat/concat.c +++ b/libavformat/concat.c @@ -245,6 +245,10 @@ static av_cold int concatf_open(URLContext *h, const char *uri, int flags) char *node_uri; int64_t size; size_t len = i; + int leading_spaces = strspn(cursor, " \n\t\r"); + + if (!cursor[leading_spaces]) + break; node_uri = av_get_token(&cursor, "\r\n"); if (!node_uri) { diff --git a/libavformat/concatdec.c b/libavformat/concatdec.c index 2557f38b26..0603c6e254 100644 --- a/libavformat/concatdec.c +++ b/libavformat/concatdec.c @@ -191,6 +191,7 @@ static int copy_stream_props(AVStream *st, AVStream *source_st) avpriv_set_pts_info(st, 64, source_st->time_base.num, source_st->time_base.den); av_dict_copy(&st->metadata, source_st->metadata, 0); + ff_stream_side_data_copy(st, source_st); return 0; } @@ -409,7 +410,7 @@ static int concat_read_close(AVFormatContext *avf) } #define MAX_ARGS 3 -#define NEEDS_UNSAFE (1 << 1) +#define NEEDS_UNSAFE (1 << 0) #define NEEDS_FILE (1 << 1) #define NEEDS_STREAM (1 << 2) diff --git a/libavformat/crcenc.c b/libavformat/crcenc.c index c58fbd6c88..9f40dd4ec0 100644 --- a/libavformat/crcenc.c +++ b/libavformat/crcenc.c @@ -28,7 +28,7 @@ typedef struct CRCState { uint32_t crcval; } CRCState; -static int crc_write_header(struct AVFormatContext *s) +static int crc_init(struct AVFormatContext *s) { CRCState *crc = s->priv_data; @@ -60,7 +60,7 @@ const AVOutputFormat ff_crc_muxer = { .priv_data_size = sizeof(CRCState), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_RAWVIDEO, - .write_header = crc_write_header, + .init = crc_init, .write_packet = crc_write_packet, .write_trailer = crc_write_trailer, .flags = AVFMT_NOTIMESTAMPS, diff --git a/libavformat/dashdec.c b/libavformat/dashdec.c index 983dc85d65..0d21989e42 100644 --- a/libavformat/dashdec.c +++ b/libavformat/dashdec.c @@ -30,8 +30,6 @@ #include "dash.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; @@ -1195,7 +1193,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 +1223,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; @@ -1833,31 +1821,6 @@ end: return ret; } -static int save_avio_options(AVFormatContext *s) -{ - DASHContext *c = s->priv_data; - const char *opts[] = { - "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", NULL }; - const char **opt = opts; - uint8_t *buf = NULL; - int ret = 0; - - while (*opt) { - if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN, &buf) >= 0) { - if (buf[0] != '\0') { - ret = av_dict_set(&c->avio_opts, *opt, buf, AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) - return ret; - } else { - av_freep(&buf); - } - } - opt++; - } - - return ret; -} - static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **opts) { @@ -2057,7 +2020,7 @@ static int dash_read_header(AVFormatContext *s) c->interrupt_callback = &s->interrupt_callback; - if ((ret = save_avio_options(s)) < 0) + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) return ret; if ((ret = parse_manifest(s, s->url, s->pb)) < 0) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 06bbf36c95..4709bc6615 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -551,7 +551,7 @@ static void write_hls_media_playlist(OutputStream *os, AVFormatContext *s, for (i = start_index; i < os->nb_segments; i++) { Segment *seg = os->segments[i]; - if (prog_date_time == 0) { + if (fabs(prog_date_time) < 1e-7) { if (os->nb_segments == 1) prog_date_time = c->start_time_s; else @@ -1396,18 +1396,18 @@ static int dash_init(AVFormatContext *s) } if (c->lhls && !c->streaming) { - av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as streaming is not enabled\n"); - c->lhls = 0; + av_log(s, AV_LOG_WARNING, "Enabling streaming as LHLS is enabled\n"); + c->streaming = 1; } if (c->lhls && !c->hls_playlist) { - av_log(s, AV_LOG_WARNING, "LHLS option will be ignored as hls_playlist is not enabled\n"); - c->lhls = 0; + av_log(s, AV_LOG_INFO, "Enabling hls_playlist as LHLS is enabled\n"); + c->hls_playlist = 1; } if (c->ldash && !c->streaming) { - av_log(s, AV_LOG_WARNING, "LDash option will be ignored as streaming is not enabled\n"); - c->ldash = 0; + av_log(s, AV_LOG_WARNING, "Enabling streaming as LDash is enabled\n"); + c->streaming = 1; } if (c->target_latency && !c->streaming) { @@ -1546,6 +1546,7 @@ static int dash_init(AVFormatContext *s) ctx->interrupt_callback = s->interrupt_callback; ctx->opaque = s->opaque; ctx->io_close = s->io_close; + ctx->io_close2 = s->io_close2; ctx->io_open = s->io_open; ctx->strict_std_compliance = s->strict_std_compliance; @@ -2333,19 +2334,19 @@ static int dash_write_trailer(AVFormatContext *s) return 0; } -static int dash_check_bitstream(struct AVFormatContext *s, const AVPacket *avpkt) +static int dash_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *avpkt) { DASHContext *c = s->priv_data; - OutputStream *os = &c->streams[avpkt->stream_index]; + OutputStream *os = &c->streams[st->index]; AVFormatContext *oc = os->ctx; if (oc->oformat->check_bitstream) { + AVStream *const ost = oc->streams[0]; int ret; - AVPacket pkt = *avpkt; - pkt.stream_index = 0; - ret = oc->oformat->check_bitstream(oc, &pkt); + ret = oc->oformat->check_bitstream(oc, ost, avpkt); if (ret == 1) { - FFStream *const sti = ffstream(s->streams[avpkt->stream_index]); - FFStream *const osti = ffstream(oc->streams[0]); + FFStream *const sti = ffstream(st); + FFStream *const osti = ffstream(ost); sti->bsfc = osti->bsfc; osti->bsfc = NULL; } diff --git a/libavformat/dca_sample_rate_tab.c b/libavformat/dca_sample_rate_tab.c new file mode 100644 index 0000000000..ed2380b0cd --- /dev/null +++ b/libavformat/dca_sample_rate_tab.c @@ -0,0 +1,25 @@ +/* + * DCA sample rates + * Copyright (C) 2004 Gildas Bazin + * Copyright (C) 2004 Benjamin Zores + * Copyright (C) 2006 Benjamin Larsson + * Copyright (C) 2007 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/dca_sample_rate_tab.h" diff --git a/libavformat/demux.c b/libavformat/demux.c index 6a4b687bf1..f895f0ba85 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -328,7 +328,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, if (s->pb && !si->data_offset) si->data_offset = avio_tell(s->pb); - si->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; + si->raw_packet_buffer_size = 0; update_stream_avctx(s); @@ -432,7 +432,7 @@ no_packet: } } - end = si->raw_packet_buffer_remaining_size <= 0 + end = si->raw_packet_buffer_size >= s->probesize || sti->probe_packets <= 0; if (end || av_log2(pd->buf_size) != av_log2(pd->buf_size - pkt->size)) { @@ -537,20 +537,19 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif for (;;) { - PacketList *pktl = si->raw_packet_buffer; + PacketListEntry *pktl = si->raw_packet_buffer.head; AVStream *st; FFStream *sti; const AVPacket *pkt1; if (pktl) { AVStream *const st = s->streams[pktl->pkt.stream_index]; - if (si->raw_packet_buffer_remaining_size <= 0) + if (si->raw_packet_buffer_size >= s->probesize) if ((err = probe_codec(s, st, NULL)) < 0) return err; if (ffstream(st)->request_probe <= 0) { - avpriv_packet_list_get(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt); - si->raw_packet_buffer_remaining_size += pkt->size; + avpriv_packet_list_get(&si->raw_packet_buffer, pkt); + si->raw_packet_buffer_size -= pkt->size; return 0; } } @@ -624,14 +623,13 @@ FF_ENABLE_DEPRECATION_WARNINGS return 0; err = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return err; } - pkt1 = &si->raw_packet_buffer_end->pkt; - si->raw_packet_buffer_remaining_size -= pkt1->size; + pkt1 = &si->raw_packet_buffer.tail->pkt; + si->raw_packet_buffer_size += pkt1->size; if ((err = probe_codec(s, st, pkt1)) < 0) return err; @@ -716,13 +714,14 @@ static int has_decode_delay_been_guessed(AVStream *st) return sti->nb_decoded_frames >= 20; } -static PacketList *get_next_pkt(AVFormatContext *s, AVStream *st, PacketList *pktl) +static PacketListEntry *get_next_pkt(AVFormatContext *s, AVStream *st, + PacketListEntry *pktl) { FFFormatContext *const si = ffformatcontext(s); if (pktl->next) return pktl->next; - if (pktl == si->packet_buffer_end) - return si->parse_queue; + if (pktl == si->packet_buffer.tail) + return si->parse_queue.head; return NULL; } @@ -774,7 +773,7 @@ static int64_t select_from_pts_buffer(AVStream *st, int64_t *pts_buffer, int64_t * of the packets in a window. */ static void update_dts_from_pts(AVFormatContext *s, int stream_index, - PacketList *pkt_buffer) + PacketListEntry *pkt_buffer) { AVStream *const st = s->streams[stream_index]; int delay = ffstream(st)->avctx->has_b_frames; @@ -804,7 +803,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, FFFormatContext *const si = ffformatcontext(s); AVStream *const st = s->streams[stream_index]; FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; uint64_t shift; @@ -823,7 +822,7 @@ static void update_initial_timestamps(AVFormatContext *s, int stream_index, if (is_relative(pts)) pts += shift; - for (PacketList *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { + for (PacketListEntry *pktl_it = pktl; pktl_it; pktl_it = get_next_pkt(s, st, pktl_it)) { if (pktl_it->pkt.stream_index != stream_index) continue; if (is_relative(pktl_it->pkt.pts)) @@ -856,7 +855,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, { FFFormatContext *const si = ffformatcontext(s); FFStream *const sti = ffstream(st); - PacketList *pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + PacketListEntry *pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; int64_t cur_dts = RELATIVE_TS_BASE; if (sti->first_dts != AV_NOPTS_VALUE) { @@ -882,7 +881,7 @@ static void update_initial_durations(AVFormatContext *s, AVStream *st, av_log(s, AV_LOG_DEBUG, "first_dts %s but no packet with dts in the queue\n", av_ts2str(sti->first_dts)); return; } - pktl = si->packet_buffer ? si->packet_buffer : si->parse_queue; + pktl = si->packet_buffer.head ? si->packet_buffer.head : si->parse_queue.head; sti->first_dts = cur_dts; } else if (sti->cur_dts != RELATIVE_TS_BASE) return; @@ -998,7 +997,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, } } - if (pkt->duration > 0 && (si->packet_buffer || si->parse_queue)) + if (pkt->duration > 0 && (si->packet_buffer.head || si->parse_queue.head)) update_initial_durations(s, st, pkt->stream_index, pkt->duration); /* Correct timestamps with byte offset if demuxers only have timestamps @@ -1179,7 +1178,7 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, out_pkt->pts = sti->parser->pts; out_pkt->dts = sti->parser->dts; out_pkt->pos = sti->parser->pos; - out_pkt->flags |= pkt->flags & AV_PKT_FLAG_DISCARD; + out_pkt->flags |= pkt->flags & (AV_PKT_FLAG_DISCARD | AV_PKT_FLAG_CORRUPT); if (sti->need_parsing == AVSTREAM_PARSE_FULL_RAW) out_pkt->pos = sti->parser->frame_offset; @@ -1195,7 +1194,6 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, compute_pkt_fields(s, st, sti->parser, out_pkt, next_dts, next_pts); ret = avpriv_packet_list_put(&si->parse_queue, - &si->parse_queue_end, out_pkt, NULL, 0); if (ret < 0) goto fail; @@ -1225,7 +1223,7 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) int ret, got_packet = 0; AVDictionary *metadata = NULL; - while (!got_packet && !si->parse_queue) { + while (!got_packet && !si->parse_queue.head) { AVStream *st; FFStream *sti; @@ -1338,8 +1336,8 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) } } - if (!got_packet && si->parse_queue) - ret = avpriv_packet_list_get(&si->parse_queue, &si->parse_queue_end, pkt); + if (!got_packet && si->parse_queue.head) + ret = avpriv_packet_list_get(&si->parse_queue, pkt); if (ret >= 0) { AVStream *const st = s->streams[pkt->stream_index]; @@ -1420,9 +1418,8 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) AVStream *st; if (!genpts) { - ret = si->packet_buffer - ? avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt) + ret = si->packet_buffer.head + ? avpriv_packet_list_get(&si->packet_buffer, pkt) : read_frame_internal(s, pkt); if (ret < 0) return ret; @@ -1430,7 +1427,7 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } for (;;) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (pktl) { AVPacket *next_pkt = &pktl->pkt; @@ -1463,15 +1460,14 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) // 3. the packets for this stream at the end of the files had valid dts. next_pkt->pts = last_dts + next_pkt->duration; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } /* read packet from packet buffer, if there is data */ st = s->streams[next_pkt->stream_index]; if (!(next_pkt->pts == AV_NOPTS_VALUE && st->discard < AVDISCARD_ALL && next_pkt->dts != AV_NOPTS_VALUE && !eof)) { - ret = avpriv_packet_list_get(&si->packet_buffer, - &si->packet_buffer_end, pkt); + ret = avpriv_packet_list_get(&si->packet_buffer, pkt); goto return_packet; } } @@ -1486,7 +1482,6 @@ int av_read_frame(AVFormatContext *s, AVPacket *pkt) } ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); @@ -2054,9 +2049,6 @@ static int try_decode_frame(AVFormatContext *s, AVStream *st, } } - if (!pkt.data && !got_picture) - ret = -1; - fail: if (do_skip_frame) { avctx->skip_frame = skip_frame; @@ -2601,12 +2593,11 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (!(ic->flags & AVFMT_FLAG_NOBUFFER)) { ret = avpriv_packet_list_put(&si->packet_buffer, - &si->packet_buffer_end, pkt1, NULL, 0); if (ret < 0) goto unref_then_goto_end; - pkt = &si->packet_buffer_end->pkt; + pkt = &si->packet_buffer.tail->pkt; } else { pkt = pkt1; } @@ -2754,8 +2745,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) // EOF already reached while reading the stream above. // So continue with reoordering DTS with whatever delay we have. - if (si->packet_buffer && !has_decode_delay_been_guessed(st)) { - update_dts_from_pts(ic, stream_index, si->packet_buffer); + if (si->packet_buffer.head && !has_decode_delay_been_guessed(st)) { + update_dts_from_pts(ic, stream_index, si->packet_buffer.head); } } } @@ -2771,11 +2762,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) /* flush the decoders */ if (sti->info->found_decoder == 1) { - do { - err = try_decode_frame(ic, st, empty_pkt, - (options && i < orig_nb_streams) - ? &options[i] : NULL); - } while (err > 0 && !has_codec_parameters(st, NULL)); + err = try_decode_frame(ic, st, empty_pkt, + (options && i < orig_nb_streams) + ? &options[i] : NULL); if (err < 0) { av_log(ic, AV_LOG_INFO, @@ -2795,7 +2784,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { if (avctx->codec_id == AV_CODEC_ID_RAWVIDEO && !avctx->codec_tag && !avctx->bits_per_coded_sample) { uint32_t tag= avcodec_pix_fmt_to_codec_tag(avctx->pix_fmt); - if (avpriv_find_pix_fmt(avpriv_get_raw_pix_fmt_tags(), tag) == avctx->pix_fmt) + if (avpriv_pix_fmt_find(PIX_FMT_LIST_RAW, tag) == avctx->pix_fmt) avctx->codec_tag= tag; } diff --git a/libavformat/dhav.c b/libavformat/dhav.c index b6bb25204c..6c1cdde32c 100644 --- a/libavformat/dhav.c +++ b/libavformat/dhav.c @@ -234,12 +234,13 @@ static int64_t get_duration(AVFormatContext *s) int64_t start_pos = avio_tell(s->pb); int64_t start = 0, end = 0; struct tm timeinfo; + int max_interations = 100000; if (!s->pb->seekable) return 0; avio_seek(s->pb, avio_size(s->pb) - 8, SEEK_SET); - while (avio_tell(s->pb) > 12) { + while (avio_tell(s->pb) > 12 && max_interations--) { if (avio_rl32(s->pb) == MKTAG('d','h','a','v')) { int seek_back = avio_rl32(s->pb); diff --git a/libavformat/dovi_isom.c b/libavformat/dovi_isom.c new file mode 100644 index 0000000000..76681b9451 --- /dev/null +++ b/libavformat/dovi_isom.c @@ -0,0 +1,118 @@ +/* + * DOVI ISO Media common code + * + * Copyright (c) 2020 Vacing Fang + * Copyright (c) 2021 quietvoid + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/dovi_meta.h" + +#include "libavcodec/put_bits.h" + +#include "avformat.h" +#include "dovi_isom.h" + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size) +{ + uint32_t buf; + AVDOVIDecoderConfigurationRecord *dovi; + size_t dovi_size; + int ret; + + if (size > (1 << 30) || size < 4) + return AVERROR_INVALIDDATA; + + dovi = av_dovi_alloc(&dovi_size); + if (!dovi) + return AVERROR(ENOMEM); + + dovi->dv_version_major = *buf_ptr++; // 8 bits + dovi->dv_version_minor = *buf_ptr++; // 8 bits + + buf = *buf_ptr++ << 8; + buf |= *buf_ptr++; + + dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits + dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits + dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit + dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit + dovi->bl_present_flag = buf & 0x01; // 1 bit + + // Has enough remaining data + if (size >= 5) { + dovi->dv_bl_signal_compatibility_id = ((*buf_ptr++) >> 4) & 0x0f; // 4 bits + } else { + // 0 stands for None + // Dolby Vision V1.2.93 profiles and levels + dovi->dv_bl_signal_compatibility_id = 0; + } + + ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, + (uint8_t *)dovi, dovi_size); + if (ret < 0) { + av_free(dovi); + return ret; + } + + av_log(s, AV_LOG_TRACE, "DOVI in dvcC/dvvC/dvwC box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); + + return 0; +} + +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi) +{ + PutBitContext pb; + + init_put_bits(&pb, out, ISOM_DVCC_DVVC_SIZE); + + put_bits(&pb, 8, dovi->dv_version_major); + put_bits(&pb, 8, dovi->dv_version_minor); + put_bits(&pb, 7, dovi->dv_profile & 0x7f); + put_bits(&pb, 6, dovi->dv_level & 0x3f); + put_bits(&pb, 1, !!dovi->rpu_present_flag); + put_bits(&pb, 1, !!dovi->el_present_flag); + put_bits(&pb, 1, !!dovi->bl_present_flag); + put_bits(&pb, 4, dovi->dv_bl_signal_compatibility_id & 0x0f); + + put_bits(&pb, 28, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + put_bits32(&pb, 0); /* reserved */ + + flush_put_bits(&pb); + + av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " + "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + dovi->dv_profile > 10 ? "dvwC" : (dovi->dv_profile > 7 ? "dvvC" : "dvcC"), + dovi->dv_version_major, dovi->dv_version_minor, + dovi->dv_profile, dovi->dv_level, + dovi->rpu_present_flag, + dovi->el_present_flag, + dovi->bl_present_flag, + dovi->dv_bl_signal_compatibility_id); +} diff --git a/libavformat/dovi_isom.h b/libavformat/dovi_isom.h new file mode 100644 index 0000000000..1526164319 --- /dev/null +++ b/libavformat/dovi_isom.h @@ -0,0 +1,35 @@ +/* + * DOVI ISO Media common code + * Copyright (c) 2021 quietvoid + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_DOVI_ISOM_H +#define AVFORMAT_DOVI_ISOM_H + +#include "libavutil/dovi_meta.h" + +#include "avformat.h" + +#define ISOM_DVCC_DVVC_SIZE 24 + +int ff_isom_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const uint8_t *buf_ptr, uint64_t size); +void ff_isom_put_dvcc_dvvc(AVFormatContext *s, uint8_t out[ISOM_DVCC_DVVC_SIZE], + AVDOVIDecoderConfigurationRecord *dovi); + +#endif /* AVFORMAT_DOVI_ISOM_H */ diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c index 9a853ba7ce..b76539b59f 100644 --- a/libavformat/dvenc.c +++ b/libavformat/dvenc.c @@ -201,8 +201,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_generic_peek_at(c->audio_data[channel], frame_ptr + d, of * 2, 2, NULL); + FFSWAP(uint8_t, frame_ptr[d], frame_ptr[d + 1]); } frame_ptr += 16 * 80; /* 15 Video DIFs + 1 Audio DIF */ } diff --git a/libavformat/fifo.c b/libavformat/fifo.c index 51d7fa5b94..86e5d369b5 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -183,6 +183,7 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) AVFormatContext *avf2 = fifo->avf; AVRational src_tb, dst_tb; int ret, s_idx; + int64_t orig_pts, orig_dts, orig_duration; if (fifo->timeshift && pkt->dts != AV_NOPTS_VALUE) atomic_fetch_sub_explicit(&fifo->queue_duration, next_duration(avf, pkt, &ctx->last_received_dts), memory_order_relaxed); @@ -198,14 +199,23 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) } } + orig_pts = pkt->pts; + orig_dts = pkt->dts; + orig_duration = pkt->duration; s_idx = pkt->stream_index; src_tb = avf->streams[s_idx]->time_base; dst_tb = avf2->streams[s_idx]->time_base; av_packet_rescale_ts(pkt, src_tb, dst_tb); ret = av_write_frame(avf2, pkt); - if (ret >= 0) + if (ret >= 0) { av_packet_unref(pkt); + } else { + // avoid scaling twice + pkt->pts = orig_pts; + pkt->dts = orig_dts; + pkt->duration = orig_duration; + } return ret; } @@ -489,6 +499,7 @@ static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat, return ret; avf2->opaque = avf->opaque; avf2->io_close = avf->io_close; + avf2->io_close2 = avf->io_close2; avf2->io_open = avf->io_open; avf2->flags = avf->flags; diff --git a/libavformat/file.c b/libavformat/file.c index 9c23f680cd..7001750c80 100644 --- a/libavformat/file.c +++ b/libavformat/file.c @@ -266,7 +266,8 @@ static int64_t file_seek(URLContext *h, int64_t pos, int whence) static int file_close(URLContext *h) { FileContext *c = h->priv_data; - return close(c->fd); + int ret = close(c->fd); + return (ret == -1) ? AVERROR(errno) : 0; } static int file_open_dir(URLContext *h) diff --git a/libavformat/flacenc.c b/libavformat/flacenc.c index f884e5d2c8..b267197ccc 100644 --- a/libavformat/flacenc.c +++ b/libavformat/flacenc.c @@ -40,7 +40,7 @@ typedef struct FlacMuxerContext { int audio_stream_idx; int waiting_pics; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; /* updated streaminfo sent by the encoder at the end */ uint8_t streaminfo[FLAC_STREAMINFO_SIZE]; @@ -306,8 +306,8 @@ static int flac_queue_flush(AVFormatContext *s) if (ret < 0) write = 0; - while (c->queue) { - avpriv_packet_list_get(&c->queue, &c->queue_end, pkt); + while (c->queue.head) { + avpriv_packet_list_get(&c->queue, pkt); if (write && (ret = flac_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -347,7 +347,7 @@ static void flac_deinit(struct AVFormatContext *s) { FlacMuxerContext *c = s->priv_data; - avpriv_packet_list_free(&c->queue, &c->queue_end); + avpriv_packet_list_free(&c->queue); for (unsigned i = 0; i < s->nb_streams; i++) av_packet_free((AVPacket **)&s->streams[i]->priv_data); } @@ -360,7 +360,7 @@ static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == c->audio_stream_idx) { if (c->waiting_pics) { /* buffer audio packets until we get all the pictures */ - ret = avpriv_packet_list_put(&c->queue, &c->queue_end, pkt, av_packet_ref, 0); + ret = avpriv_packet_list_put(&c->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n"); c->waiting_pics = 0; diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 44a7e5f93c..b9e36b3ff1 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -461,6 +461,8 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, int64_t m d = av_int2double(avio_rb64(ioc)); if (isnan(d) || d < INT64_MIN || d > INT64_MAX) goto invalid; + if (current_array == × && (d <= INT64_MIN / 1000 || d >= INT64_MAX / 1000)) + goto invalid; current_array[0][i] = d; } if (times && filepositions) { diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index 3f24c7e192..66c530a2ff 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -24,6 +24,7 @@ #include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/mathematics.h" +#include "libavcodec/mpeg4audio.h" #include "avio_internal.h" #include "avio.h" #include "avc.h" @@ -33,7 +34,6 @@ #include "metadata.h" #include "libavutil/opt.h" #include "libavcodec/put_bits.h" -#include "libavcodec/aacenctab.h" static const AVCodecTag flv_video_codec_ids[] = { @@ -284,8 +284,8 @@ static void write_metadata(AVFormatContext *s, unsigned int ts) avio_w8(pb, FLV_TAG_TYPE_META); // tag type META flv->metadata_size_pos = avio_tell(pb); avio_wb24(pb, 0); // size of data part (sum of all parts below) - avio_wb24(pb, ts); // timestamp - avio_wb32(pb, 0); // reserved + put_timestamp(pb, ts); // timestamp + avio_wb24(pb, 0); // reserved /* now data of data_size size */ @@ -514,7 +514,7 @@ static void flv_write_codec_header(AVFormatContext* s, AVCodecParameters* par, i for (samplerate_index = 0; samplerate_index < 16; samplerate_index++) if (flv->audio_par->sample_rate - == mpeg4audio_sample_rates[samplerate_index]) + == ff_mpeg4audio_sample_rates[samplerate_index]) break; init_put_bits(&pbc, data, sizeof(data)); @@ -576,15 +576,9 @@ static int flv_append_keyframe_info(AVFormatContext *s, FLVContext *flv, double static int shift_data(AVFormatContext *s) { - int ret = 0; - int n = 0; + int ret; int64_t metadata_size = 0; FLVContext *flv = s->priv_data; - int64_t pos, pos_end = avio_tell(s->pb); /* Save the pre-shift size. */ - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; metadata_size = flv->filepositions_count * 9 * 2 + 10; /* filepositions and times value */ metadata_size += 2 + 13; /* filepositions String */ @@ -596,58 +590,17 @@ static int shift_data(AVFormatContext *s) if (metadata_size < 0) return metadata_size; - buf = av_malloc_array(metadata_size, 2); - if (!buf) { - return AVERROR(ENOMEM); - } - read_buf[0] = buf; - read_buf[1] = buf + metadata_size; + ret = ff_format_shift_data(s, flv->keyframes_info_offset, metadata_size); + if (ret < 0) + return ret; avio_seek(s->pb, flv->metadata_size_pos, SEEK_SET); avio_wb24(s->pb, flv->metadata_totalsize + metadata_size); - avio_seek(s->pb, flv->metadata_totalsize_pos, SEEK_SET); + avio_seek(s->pb, flv->metadata_totalsize_pos + metadata_size, SEEK_SET); avio_wb32(s->pb, flv->metadata_totalsize + 11 + metadata_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 " - "the second pass (add_keyframe_index)\n", s->url); - goto end; - } - - /* Get ready for writing. */ - avio_seek(s->pb, flv->keyframes_info_offset + metadata_size, SEEK_SET); - - /* start reading at where the keyframe index information will be placed */ - avio_seek(read_pb, flv->keyframes_info_offset, 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], metadata_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most keyframe *filepositions* and *times* size */ - READ_BLOCK; - do { - 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); - - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return 0; } static int flv_init(struct AVFormatContext *s) @@ -1083,10 +1036,10 @@ fail: return ret; } -static int flv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int flv_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/format.c b/libavformat/format.c index 387627009e..52b85c16a2 100644 --- a/libavformat/format.c +++ b/libavformat/format.c @@ -158,6 +158,8 @@ const AVInputFormat *av_probe_input_format3(const AVProbeData *pd, } while ((fmt1 = av_demuxer_iterate(&i))) { + if (fmt1->flags & AVFMT_EXPERIMENTAL) + continue; if (!is_opened == !(fmt1->flags & AVFMT_NOFILE) && strcmp(fmt1->name, "image2")) continue; score = 0; diff --git a/libavformat/ftp.c b/libavformat/ftp.c index 69caa7670c..883668b37b 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -250,13 +250,19 @@ static int ftp_auth(FTPContext *s) if (strpbrk(s->user, "\r\n")) return AVERROR(EINVAL); - snprintf(buf, sizeof(buf), "USER %s\r\n", s->user); + err = snprintf(buf, sizeof(buf), "USER %s\r\n", s->user); + if (err >= sizeof(buf)) + return AVERROR(ENOSYS); + err = ftp_send_command(s, buf, user_codes, NULL); if (err == 331) { if (s->password) { if (strpbrk(s->password, "\r\n")) return AVERROR(EINVAL); - snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password); + err = snprintf(buf, sizeof(buf), "PASS %s\r\n", s->password); + if (err >= sizeof(buf)) + return AVERROR(ENOSYS); + err = ftp_send_command(s, buf, pass_codes, NULL); } else return AVERROR(EACCES); @@ -397,9 +403,13 @@ static int ftp_file_size(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; char *res = NULL; + int ret; static const int size_codes[] = {213, 0}; - snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); + if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) { s->filesize = strtoll(&res[4], NULL, 10); } else { @@ -416,9 +426,12 @@ static int ftp_retrieve(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; static const int retr_codes[] = {150, 125, 0}; - int resp_code; + int resp_code, ret; + + ret = snprintf(command, sizeof(command), "RETR %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "RETR %s\r\n", s->path); resp_code = ftp_send_command(s, command, retr_codes, NULL); if (resp_code != 125 && resp_code != 150) return AVERROR(EIO); @@ -432,9 +445,12 @@ static int ftp_store(FTPContext *s) { char command[CONTROL_BUFFER_SIZE]; static const int stor_codes[] = {150, 125, 0}; - int resp_code; + int resp_code, ret; + + ret = snprintf(command, sizeof(command), "STOR %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "STOR %s\r\n", s->path); resp_code = ftp_send_command(s, command, stor_codes, NULL); if (resp_code != 125 && resp_code != 150) return AVERROR(EIO); @@ -471,8 +487,12 @@ static int ftp_set_dir(FTPContext *s) { static const int cwd_codes[] = {250, 550, 0}; /* 550 is incorrect code */ char command[MAX_URL_SIZE]; + int ret; + + ret = snprintf(command, sizeof(command), "CWD %s\r\n", s->path); + if (ret >= sizeof(command)) + return AVERROR(ENOSYS); - snprintf(command, sizeof(command), "CWD %s\r\n", s->path); if (ftp_send_command(s, command, cwd_codes, NULL) != 250) return AVERROR(EIO); return 0; @@ -1082,13 +1102,23 @@ static int ftp_delete(URLContext *h) if ((ret = ftp_connect(h, h->filename)) < 0) goto cleanup; - snprintf(command, sizeof(command), "DELE %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "DELE %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, del_codes, NULL) == 250) { ret = 0; goto cleanup; } - snprintf(command, sizeof(command), "RMD %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "RMD %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rmd_codes, NULL) == 250) ret = 0; else @@ -1110,7 +1140,12 @@ static int ftp_move(URLContext *h_src, URLContext *h_dst) if ((ret = ftp_connect(h_src, h_src->filename)) < 0) goto cleanup; - snprintf(command, sizeof(command), "RNFR %s\r\n", s->path); + ret = snprintf(command, sizeof(command), "RNFR %s\r\n", s->path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rnfr_codes, NULL) != 350) { ret = AVERROR(EIO); goto cleanup; @@ -1119,7 +1154,12 @@ static int ftp_move(URLContext *h_src, URLContext *h_dst) av_url_split(0, 0, 0, 0, 0, 0, 0, path, sizeof(path), h_dst->filename); - snprintf(command, sizeof(command), "RNTO %s\r\n", path); + ret = snprintf(command, sizeof(command), "RNTO %s\r\n", path); + if (ret >= sizeof(command)) { + ret = AVERROR(ENOSYS); + goto cleanup; + } + if (ftp_send_command(s, command, rnto_codes, NULL) == 250) ret = 0; else diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c index e5353bac65..2a52019120 100644 --- a/libavformat/hdsenc.c +++ b/libavformat/hdsenc.c @@ -93,19 +93,17 @@ static int parse_header(OutputStream *os, const uint8_t *buf, int buf_size) if (os->nb_extra_packets >= FF_ARRAY_ELEMS(os->extra_packets)) return AVERROR_INVALIDDATA; os->extra_packet_sizes[os->nb_extra_packets] = size; - os->extra_packets[os->nb_extra_packets] = av_malloc(size); + os->extra_packets[os->nb_extra_packets] = av_memdup(buf, size); if (!os->extra_packets[os->nb_extra_packets]) return AVERROR(ENOMEM); - memcpy(os->extra_packets[os->nb_extra_packets], buf, size); os->nb_extra_packets++; } else if (type == 0x12) { if (os->metadata) return AVERROR_INVALIDDATA; os->metadata_size = size - 11 - 4; - os->metadata = av_malloc(os->metadata_size); + os->metadata = av_memdup(buf + 11, os->metadata_size); if (!os->metadata) return AVERROR(ENOMEM); - memcpy(os->metadata, buf + 11, os->metadata_size); } buf += size; buf_size -= size; @@ -370,7 +368,7 @@ static int hds_write_header(AVFormatContext *s) ctx->flags = s->flags; ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), - AVIO_FLAG_WRITE, os, + 1, os, NULL, hds_write, NULL); if (!ctx->pb) { return AVERROR(ENOMEM); diff --git a/libavformat/hls.c b/libavformat/hls.c index 52a031ed54..8c526f748f 100644 --- a/libavformat/hls.c +++ b/libavformat/hls.c @@ -1284,7 +1284,6 @@ static int open_input(HLSContext *c, struct playlist *pls, struct segment *seg, char iv[33], key[33], url[MAX_URL_SIZE]; ff_data_to_hex(iv, seg->iv, sizeof(seg->iv), 0); ff_data_to_hex(key, pls->key, sizeof(pls->key), 0); - iv[32] = key[32] = '\0'; if (strstr(seg->url, "://")) snprintf(url, sizeof(url), "crypto+%s", seg->url); else @@ -1718,28 +1717,6 @@ static int64_t select_cur_seq_no(HLSContext *c, struct playlist *pls) return pls->start_seq_no; } -static int save_avio_options(AVFormatContext *s) -{ - HLSContext *c = s->priv_data; - static const char * const opts[] = { - "headers", "http_proxy", "user_agent", "cookies", "referer", "rw_timeout", "icy", NULL }; - const char * const * opt = opts; - uint8_t *buf; - int ret = 0; - - while (*opt) { - if (av_opt_get(s->pb, *opt, AV_OPT_SEARCH_CHILDREN | AV_OPT_ALLOW_NULL, &buf) >= 0) { - ret = av_dict_set(&c->avio_opts, *opt, buf, - AV_DICT_DONT_STRDUP_VAL); - if (ret < 0) - return ret; - } - opt++; - } - - return ret; -} - static int nested_io_open(AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **opts) { @@ -1885,7 +1862,7 @@ static int hls_read_header(AVFormatContext *s) c->first_timestamp = AV_NOPTS_VALUE; c->cur_timestamp = AV_NOPTS_VALUE; - if ((ret = save_avio_options(s)) < 0) + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) return ret; /* XXX: Some HLS servers don't like being sent the range header, @@ -2074,7 +2051,6 @@ 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); - key[32] = '\0'; av_dict_set(&options, "decryption_key", key, AV_OPT_FLAG_DECODING_PARAM); } else if (!c->crypto_ctx.aes_ctx) { c->crypto_ctx.aes_ctx = av_aes_alloc(); diff --git a/libavformat/hls_sample_encryption.c b/libavformat/hls_sample_encryption.c index 396fe97921..3dbaff717e 100644 --- a/libavformat/hls_sample_encryption.c +++ b/libavformat/hls_sample_encryption.c @@ -26,6 +26,8 @@ * https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/HLS_Sample_Encryption */ +#include "libavutil/channel_layout.h" + #include "hls_sample_encryption.h" #include "libavcodec/adts_header.h" @@ -129,7 +131,7 @@ 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 = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; @@ -268,7 +270,7 @@ static int get_next_adts_frame(CodecParserContext *ctx, AudioFrame *frame) /* Find next sync word 0xFFF */ while (ctx->buf_ptr < ctx->buf_end - 1) { - if (*ctx->buf_ptr == 0xFF && *(ctx->buf_ptr + 1) & 0xF0 == 0xF0) + if (*ctx->buf_ptr == 0xFF && (*(ctx->buf_ptr + 1) & 0xF0) == 0xF0) break; ctx->buf_ptr++; } diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c index 98608a834a..ef8973cea1 100644 --- a/libavformat/hlsenc.c +++ b/libavformat/hlsenc.c @@ -745,7 +745,6 @@ static int do_encrypt(AVFormatContext *s, VariantStream *vs) memcpy(iv, hls->iv, sizeof(iv)); } ff_data_to_hex(buf, iv, sizeof(iv), 0); - buf[32] = '\0'; memcpy(hls->iv_string, buf, sizeof(hls->iv_string)); } @@ -867,6 +866,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) oc->opaque = s->opaque; oc->io_open = s->io_open; oc->io_close = s->io_close; + oc->io_close2 = s->io_close2; oc->strict_std_compliance = s->strict_std_compliance; av_dict_copy(&oc->metadata, s->metadata, 0); @@ -900,6 +900,7 @@ static int hls_mux_init(AVFormatContext *s, VariantStream *vs) st->sample_aspect_ratio = vs->streams[i]->sample_aspect_ratio; st->time_base = vs->streams[i]->time_base; av_dict_copy(&st->metadata, vs->streams[i]->metadata, 0); + st->id = vs->streams[i]->id; } vs->start_pos = 0; @@ -2382,10 +2383,9 @@ static int64_t append_single_file(AVFormatContext *s, VariantStream *vs) } do { - memset(buf, 0, sizeof(BUFSIZE)); read_byte = avio_read(vs->out, buf, BUFSIZE); - avio_write(vs->out_single_file, buf, read_byte); if (read_byte > 0) { + avio_write(vs->out_single_file, buf, read_byte); total_size += read_byte; ret = total_size; } @@ -3102,11 +3102,14 @@ static const AVOption options[] = { {"hls_init_time", "set segment length at init list", OFFSET(init_time), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, E}, {"hls_list_size", "set maximum number of playlist entries", OFFSET(max_nb_segments), AV_OPT_TYPE_INT, {.i64 = 5}, 0, INT_MAX, E}, {"hls_delete_threshold", "set number of unreferenced segments to keep before deleting", OFFSET(hls_delete_threshold), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E}, - {"hls_ts_options","set hls mpegts list of options for the container format used for hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E}, +#if FF_HLS_TS_OPTIONS + {"hls_ts_options","set hls mpegts list of options for the container format used for hls (deprecated, use hls_segment_options instead of it.)", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E | AV_OPT_FLAG_DEPRECATED}, +#endif {"hls_vtt_options","set hls vtt list of options for the container format used for hls", OFFSET(vtt_format_options_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E}, {"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, + {"hls_segment_options","set segments files format options of hls", OFFSET(format_options), AV_OPT_TYPE_DICT, {.str = NULL}, 0, 0, E}, {"hls_segment_size", "maximum size per segment file, (in bytes)", OFFSET(max_seg_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, {"hls_key_info_file", "file with key URI and key file path", OFFSET(key_info_file), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, {"hls_enc", "enable AES128 encryption support", OFFSET(encrypt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E}, diff --git a/libavformat/http.c b/libavformat/http.c index 476b9a8456..4415a26f2c 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -69,7 +69,9 @@ typedef struct HTTPContext { uint64_t chunksize; int chunkend; uint64_t off, end_off, filesize; + char *uri; char *location; + int cache_redirect; HTTPAuthState auth_state; HTTPAuthState proxy_auth_state; char *http_proxy; @@ -126,6 +128,7 @@ typedef struct HTTPContext { int is_multi_client; HandshakeState handshake_step; int is_connected_server; + int short_seek_size; } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -167,6 +170,8 @@ static const AVOption options[] = { { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E }, { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E }, { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E}, + { "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 } }; @@ -192,7 +197,7 @@ static int http_open_cnx_internal(URLContext *h, AVDictionary **options) char *hashmark; char hostname[1024], hoststr[1024], proto[10]; char auth[1024], proxyauth[1024] = ""; - char path1[MAX_URL_SIZE], sanitized_path[MAX_URL_SIZE]; + 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; HTTPContext *s = h->priv_data; @@ -430,11 +435,17 @@ int ff_http_do_new_request2(URLContext *h, const char *uri, AVDictionary **opts) s->chunkend = 0; s->off = 0; s->icy_data_read = 0; + av_free(s->location); s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); + av_free(s->uri); + s->uri = av_strdup(uri); + if (!s->uri) + return AVERROR(ENOMEM); + if ((ret = av_opt_set_dict(s, opts)) < 0) return ret; @@ -621,9 +632,15 @@ static int http_open(URLContext *h, const char *uri, int flags, h->is_streamed = 1; s->filesize = UINT64_MAX; + s->location = av_strdup(uri); if (!s->location) return AVERROR(ENOMEM); + + s->uri = av_strdup(uri); + if (!s->uri) + return AVERROR(ENOMEM); + if (options) av_dict_copy(&s->chained_options, *options, 0); @@ -649,6 +666,7 @@ bail_out: if (ret < 0) { av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_freep(&s->uri); } return ret; } @@ -1767,6 +1785,7 @@ static int http_close(URLContext *h) ffurl_closep(&s->hd); av_dict_free(&s->chained_options); av_dict_free(&s->cookie_dict); + av_freep(&s->uri); return ret; } @@ -1808,6 +1827,16 @@ 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)) { + char *new_uri; + new_uri = av_strdup(s->uri); + if (!new_uri) + return AVERROR(ENOMEM); + av_free(s->location); + s->location = new_uri; + } + /* we save the old context in case the seek fails */ old_buf_size = s->buf_end - s->buf_ptr; memcpy(old_buf, s->buf_ptr, old_buf_size); @@ -1842,6 +1871,8 @@ static int http_get_file_handle(URLContext *h) static int http_get_short_seek(URLContext *h) { HTTPContext *s = h->priv_data; + if (s->short_seek_size >= 1) + return s->short_seek_size; return ffurl_get_short_seek(s->hd); } diff --git a/libavformat/httpauth.c b/libavformat/httpauth.c index 4f79c78edc..0a98ff80a5 100644 --- a/libavformat/httpauth.c +++ b/libavformat/httpauth.c @@ -156,7 +156,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, for (i = 0; i < 2; i++) cnonce_buf[i] = av_get_random_seed(); ff_data_to_hex(cnonce, (const uint8_t*) cnonce_buf, sizeof(cnonce_buf), 1); - cnonce[2*sizeof(cnonce_buf)] = 0; md5ctx = av_md5_alloc(); if (!md5ctx) @@ -166,7 +165,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, username, ":", state->realm, ":", password, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); - A1hash[32] = 0; if (!strcmp(digest->algorithm, "") || !strcmp(digest->algorithm, "MD5")) { } else if (!strcmp(digest->algorithm, "MD5-sess")) { @@ -174,7 +172,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, A1hash, ":", digest->nonce, ":", cnonce, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A1hash, hash, 16, 1); - A1hash[32] = 0; } else { /* Unsupported algorithm */ av_free(md5ctx); @@ -185,7 +182,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, method, ":", uri, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(A2hash, hash, 16, 1); - A2hash[32] = 0; av_md5_init(md5ctx); update_md5_strings(md5ctx, A1hash, ":", digest->nonce, NULL); @@ -195,7 +191,6 @@ static char *make_digest_auth(HTTPAuthState *state, const char *username, update_md5_strings(md5ctx, ":", A2hash, NULL); av_md5_final(md5ctx, hash); ff_data_to_hex(response, hash, 16, 1); - response[32] = 0; av_free(md5ctx); diff --git a/libavformat/imf.h b/libavformat/imf.h new file mode 100644 index 0000000000..62c4468ce9 --- /dev/null +++ b/libavformat/imf.h @@ -0,0 +1,207 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) Sandflow Consulting LLC + * + * 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Public header file for the processing of Interoperable Master Format (IMF) + * packages. + * + * @author Pierre-Anthony Lemieux + * @author Valentin Noel + * @file + * @ingroup lavu_imf + */ + +#ifndef AVFORMAT_IMF_H +#define AVFORMAT_IMF_H + +#include "avformat.h" +#include "libavformat/avio.h" +#include "libavutil/rational.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 + */ +typedef struct FFIMFBaseResource { + AVRational edit_rate; /**< BaseResourceType/EditRate */ + uint32_t entry_point; /**< BaseResourceType/EntryPoint */ + uint32_t duration; /**< BaseResourceType/Duration */ + uint32_t repeat_count; /**< BaseResourceType/RepeatCount */ +} FFIMFBaseResource; + +/** + * IMF Composition Playlist Track File Resource + */ +typedef struct FFIMFTrackFileResource { + FFIMFBaseResource base; + FFIMFUUID track_file_uuid; /**< TrackFileResourceType/TrackFileId */ +} FFIMFTrackFileResource; + +/** + * IMF Marker + */ +typedef struct FFIMFMarker { + xmlChar *label_utf8; /**< Marker/Label */ + xmlChar *scope_utf8; /**< Marker/Label/\@scope */ + uint32_t offset; /**< Marker/Offset */ +} FFIMFMarker; + +/** + * IMF Composition Playlist Marker Resource + */ +typedef struct FFIMFMarkerResource { + FFIMFBaseResource base; + uint32_t marker_count; /**< Number of Marker elements */ + FFIMFMarker *markers; /**< Marker elements */ +} FFIMFMarkerResource; + +/** + * IMF Composition Playlist Virtual Track + */ +typedef struct FFIMFBaseVirtualTrack { + FFIMFUUID id_uuid; /**< TrackId associated with the Virtual Track */ +} FFIMFBaseVirtualTrack; + +/** + * IMF Composition Playlist Virtual Track that consists of Track File Resources + */ +typedef struct FFIMFTrackFileVirtualTrack { + FFIMFBaseVirtualTrack base; + uint32_t resource_count; /**< Number of Resource elements present in the Virtual Track */ + FFIMFTrackFileResource *resources; /**< Resource elements of the Virtual Track */ + unsigned int resources_alloc_sz; /**< Size of the resources buffer */ +} FFIMFTrackFileVirtualTrack; + +/** + * IMF Composition Playlist Virtual Track that consists of Marker Resources + */ +typedef struct FFIMFMarkerVirtualTrack { + FFIMFBaseVirtualTrack base; + uint32_t resource_count; /**< Number of Resource elements present in the Virtual Track */ + FFIMFMarkerResource *resources; /**< Resource elements of the Virtual Track */ +} FFIMFMarkerVirtualTrack; + +/** + * IMF Composition Playlist + */ +typedef struct FFIMFCPL { + FFIMFUUID 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 */ + FFIMFTrackFileVirtualTrack *main_image_2d_track; /**< Main Image Virtual Track */ + uint32_t main_audio_track_count; /**< Number of Main Audio Virtual Tracks */ + FFIMFTrackFileVirtualTrack *main_audio_tracks; /**< Main Audio Virtual Tracks */ +} FFIMFCPL; + +/** + * Parse an IMF CompositionPlaylist element into the FFIMFCPL data structure. + * @param[in] doc An XML document from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl); + +/** + * Parse an IMF Composition Playlist document into the FFIMFCPL data structure. + * @param[in] in The context from which the CPL is read. + * @param[out] cpl Pointer to a memory area (allocated by the client), where the + * function writes a pointer to the newly constructed FFIMFCPL structure (or + * NULL if the CPL could not be parsed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + * @return A non-zero value in case of an error. + */ +int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl); + +/** + * Allocates and initializes an FFIMFCPL data structure. + * @return A pointer to the newly constructed FFIMFCPL structure (or NULL if the + * structure could not be constructed). The client is responsible for freeing + * the FFIMFCPL structure using ff_imf_cpl_free(). + */ +FFIMFCPL *ff_imf_cpl_alloc(void); + +/** + * Deletes an FFIMFCPL data structure previously instantiated with ff_imf_cpl_alloc(). + * @param[in] cpl The FFIMFCPL structure to delete. + */ +void ff_imf_cpl_free(FFIMFCPL *cpl); + +/** + * Reads an unsigned 32-bit integer from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number); + +/** + * Reads an AVRational from an XML element + * @return 0 on success, < 0 AVERROR code on error. + */ +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]); + +/** + * Returns the first child element with the specified local name + * @return A pointer to the child element, or NULL if no such child element exists. + */ +xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8); + +#endif diff --git a/libavformat/imf_cpl.c b/libavformat/imf_cpl.c new file mode 100644 index 0000000000..f2ad9c05d6 --- /dev/null +++ b/libavformat/imf_cpl.c @@ -0,0 +1,844 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) Sandflow Consulting LLC + * + * 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Implements IMP CPL processing + * + * @author Pierre-Anthony Lemieux + * @file + * @ingroup lavu_imf + */ + +#include "imf.h" +#include "libavformat/mxf.h" +#include "libavutil/bprint.h" +#include "libavutil/error.h" +#include + +xmlNodePtr ff_imf_xml_get_child_element_by_name(xmlNodePtr parent, const char *name_utf8) +{ + xmlNodePtr cur_element; + + cur_element = xmlFirstElementChild(parent); + while (cur_element) { + if (xmlStrcmp(cur_element->name, name_utf8) == 0) + return cur_element; + + cur_element = xmlNextElementSibling(cur_element); + } + return NULL; +} + +int ff_imf_xml_read_uuid(xmlNodePtr element, uint8_t uuid[16]) +{ + 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) { + av_log(NULL, AV_LOG_ERROR, "Invalid UUID\n"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +int ff_imf_xml_read_rational(xmlNodePtr element, AVRational *rational) +{ + xmlChar *element_text = NULL; + int ret = 0; + + element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (sscanf(element_text, "%i %i", &rational->num, &rational->den) != 2) { + av_log(NULL, AV_LOG_ERROR, "Invalid rational number\n"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +int ff_imf_xml_read_uint32(xmlNodePtr element, uint32_t *number) +{ + xmlChar *element_text = NULL; + int ret = 0; + + element_text = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1); + if (sscanf(element_text, "%" PRIu32, number) != 1) { + av_log(NULL, AV_LOG_ERROR, "Invalid unsigned 32-bit integer"); + ret = AVERROR_INVALIDDATA; + } + xmlFree(element_text); + + return ret; +} + +static void imf_base_virtual_track_init(FFIMFBaseVirtualTrack *track) +{ + memset(track->id_uuid, 0, sizeof(track->id_uuid)); +} + +static void imf_marker_virtual_track_init(FFIMFMarkerVirtualTrack *track) +{ + imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); + track->resource_count = 0; + track->resources = NULL; +} + +static void imf_trackfile_virtual_track_init(FFIMFTrackFileVirtualTrack *track) +{ + imf_base_virtual_track_init((FFIMFBaseVirtualTrack *)track); + track->resource_count = 0; + track->resources_alloc_sz = 0; + track->resources = NULL; +} + +static void imf_base_resource_init(FFIMFBaseResource *rsrc) +{ + rsrc->duration = 0; + rsrc->edit_rate = av_make_q(0, 1); + rsrc->entry_point = 0; + rsrc->repeat_count = 1; +} + +static void imf_marker_resource_init(FFIMFMarkerResource *rsrc) +{ + imf_base_resource_init((FFIMFBaseResource *)rsrc); + rsrc->marker_count = 0; + rsrc->markers = NULL; +} + +static void imf_marker_init(FFIMFMarker *marker) +{ + marker->label_utf8 = NULL; + marker->offset = 0; + marker->scope_utf8 = NULL; +} + +static void imf_trackfile_resource_init(FFIMFTrackFileResource *rsrc) +{ + imf_base_resource_init((FFIMFBaseResource *)rsrc); + memset(rsrc->track_file_uuid, 0, sizeof(rsrc->track_file_uuid)); +} + +static int fill_content_title(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "ContentTitle"))) { + av_log(NULL, AV_LOG_ERROR, "ContentTitle element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + cpl->content_title_utf8 = xmlNodeListGetString(cpl_element->doc, + element->xmlChildrenNode, + 1); + + return 0; +} + +static int fill_edit_rate(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "EditRate"))) { + av_log(NULL, AV_LOG_ERROR, "EditRate element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + + return ff_imf_xml_read_rational(element, &cpl->edit_rate); +} + +static int fill_id(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + + if (!(element = ff_imf_xml_get_child_element_by_name(cpl_element, "Id"))) { + av_log(NULL, AV_LOG_ERROR, "Id element not found in the IMF CPL\n"); + return AVERROR_INVALIDDATA; + } + + return ff_imf_xml_read_uuid(element, cpl->id_uuid); +} + +static int fill_marker(xmlNodePtr marker_elem, FFIMFMarker *marker) +{ + xmlNodePtr element = NULL; + int ret = 0; + + /* read Offset */ + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Offset"))) { + av_log(NULL, AV_LOG_ERROR, "Offset element not found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uint32(element, &marker->offset))) + return ret; + + /* read Label and Scope */ + if (!(element = ff_imf_xml_get_child_element_by_name(marker_elem, "Label"))) { + av_log(NULL, AV_LOG_ERROR, "Label element not found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if (!(marker->label_utf8 = xmlNodeListGetString(element->doc, element->xmlChildrenNode, 1))) { + av_log(NULL, AV_LOG_ERROR, "Empty Label element found in a Marker\n"); + return AVERROR_INVALIDDATA; + } + if (!(marker->scope_utf8 = xmlGetNoNsProp(element, "scope"))) { + marker->scope_utf8 + = xmlCharStrdup("http://www.smpte-ra.org/schemas/2067-3/2013#standard-markers"); + if (!marker->scope_utf8) { + xmlFree(marker->label_utf8); + return AVERROR(ENOMEM); + } + } + + return ret; +} + +static int fill_base_resource(xmlNodePtr resource_elem, FFIMFBaseResource *resource, FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + /* read EditRate */ + if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "EditRate"))) { + resource->edit_rate = cpl->edit_rate; + } else if ((ret = ff_imf_xml_read_rational(element, &resource->edit_rate))) { + av_log(NULL, AV_LOG_ERROR, "Invalid EditRate element found in a Resource\n"); + return ret; + } + + /* read EntryPoint */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "EntryPoint"))) { + if ((ret = ff_imf_xml_read_uint32(element, &resource->entry_point))) { + av_log(NULL, AV_LOG_ERROR, "Invalid EntryPoint element found in a Resource\n"); + return ret; + } + } else { + resource->entry_point = 0; + } + + /* read IntrinsicDuration */ + if (!(element = ff_imf_xml_get_child_element_by_name(resource_elem, "IntrinsicDuration"))) { + av_log(NULL, AV_LOG_ERROR, "IntrinsicDuration element missing from Resource\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { + av_log(NULL, AV_LOG_ERROR, "Invalid IntrinsicDuration element found in a Resource\n"); + return ret; + } + resource->duration -= resource->entry_point; + + /* read SourceDuration */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "SourceDuration"))) { + if ((ret = ff_imf_xml_read_uint32(element, &resource->duration))) { + av_log(NULL, AV_LOG_ERROR, "SourceDuration element missing from Resource\n"); + return ret; + } + } + + /* read RepeatCount */ + if ((element = ff_imf_xml_get_child_element_by_name(resource_elem, "RepeatCount"))) + ret = ff_imf_xml_read_uint32(element, &resource->repeat_count); + + return ret; +} + +static int fill_trackfile_resource(xmlNodePtr tf_resource_elem, + FFIMFTrackFileResource *tf_resource, + FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + if ((ret = fill_base_resource(tf_resource_elem, (FFIMFBaseResource *)tf_resource, cpl))) + return ret; + + /* read TrackFileId */ + if ((element = ff_imf_xml_get_child_element_by_name(tf_resource_elem, "TrackFileId"))) { + if ((ret = ff_imf_xml_read_uuid(element, tf_resource->track_file_uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackFileId element found in Resource\n"); + return ret; + } + } else { + av_log(NULL, AV_LOG_ERROR, "TrackFileId element missing from Resource\n"); + return AVERROR_INVALIDDATA; + } + + return ret; +} + +static int fill_marker_resource(xmlNodePtr marker_resource_elem, + FFIMFMarkerResource *marker_resource, + FFIMFCPL *cpl) +{ + xmlNodePtr element = NULL; + int ret = 0; + + if ((ret = fill_base_resource(marker_resource_elem, (FFIMFBaseResource *)marker_resource, cpl))) + return ret; + + /* read markers */ + element = xmlFirstElementChild(marker_resource_elem); + while (element) { + if (xmlStrcmp(element->name, "Marker") == 0) { + void *tmp; + + if (marker_resource->marker_count == UINT32_MAX) + return AVERROR(ENOMEM); + tmp = av_realloc_array(marker_resource->markers, + marker_resource->marker_count + 1, + sizeof(FFIMFMarker)); + if (!tmp) + return AVERROR(ENOMEM); + marker_resource->markers = tmp; + + imf_marker_init(&marker_resource->markers[marker_resource->marker_count]); + ret = fill_marker(element, + &marker_resource->markers[marker_resource->marker_count]); + marker_resource->marker_count++; + if (ret) + return ret; + } + + element = xmlNextElementSibling(element); + } + + return ret; +} + +static int push_marker_sequence(xmlNodePtr marker_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + unsigned long resource_elem_count; + void *tmp; + + /* read TrackID element */ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from Sequence\n"); + return AVERROR_INVALIDDATA; + } + if (ff_imf_xml_read_uuid(track_id_elem, uuid)) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in Sequence\n"); + return AVERROR_INVALIDDATA; + } + av_log(NULL, + AV_LOG_DEBUG, + "Processing IMF CPL Marker Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", + UID_ARG(uuid)); + + /* create main marker virtual track if it does not exist */ + if (!cpl->main_markers_track) { + cpl->main_markers_track = av_malloc(sizeof(FFIMFMarkerVirtualTrack)); + 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)); + + } else if (memcmp(cpl->main_markers_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + av_log(NULL, AV_LOG_ERROR, "Multiple marker virtual tracks were found\n"); + return AVERROR_INVALIDDATA; + } + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(marker_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || cpl->main_markers_track->resource_count > UINT32_MAX - resource_elem_count) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cpl->main_markers_track->resources, + cpl->main_markers_track->resource_count + resource_elem_count, + sizeof(FFIMFMarkerResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Marker Resources\n"); + return AVERROR(ENOMEM); + } + cpl->main_markers_track->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_marker_resource_init(&cpl->main_markers_track->resources[cpl->main_markers_track->resource_count]); + ret = fill_marker_resource(resource_elem, + &cpl->main_markers_track->resources[cpl->main_markers_track->resource_count], + cpl); + cpl->main_markers_track->resource_count++; + if (ret) + return ret; + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return ret; +} + +static int has_stereo_resources(xmlNodePtr element) +{ + if (xmlStrcmp(element->name, "Left") == 0 || xmlStrcmp(element->name, "Right") == 0) + return 1; + + element = xmlFirstElementChild(element); + while (element) { + if (has_stereo_resources(element)) + return 1; + + element = xmlNextElementSibling(element); + } + + return 0; +} + +static int push_main_audio_sequence(xmlNodePtr audio_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + unsigned long resource_elem_count; + FFIMFTrackFileVirtualTrack *vt = NULL; + void *tmp; + + /* read TrackID element */ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); + return ret; + } + av_log(NULL, + AV_LOG_DEBUG, + "Processing IMF CPL Audio Sequence for Virtual Track " FF_IMF_UUID_FORMAT "\n", + UID_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) { + vt = &cpl->main_audio_tracks[i]; + break; + } + } + + /* create a main audio virtual track if none exists for the sequence */ + if (!vt) { + if (cpl->main_audio_track_count == UINT32_MAX) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cpl->main_audio_tracks, + cpl->main_audio_track_count + 1, + sizeof(FFIMFTrackFileVirtualTrack)); + if (!tmp) + return AVERROR(ENOMEM); + + cpl->main_audio_tracks = tmp; + 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)); + } + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(audio_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || vt->resource_count > UINT32_MAX - resource_elem_count) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(vt->resources, + &vt->resources_alloc_sz, + (vt->resource_count + resource_elem_count) + * sizeof(FFIMFTrackFileResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Audio Resources\n"); + return AVERROR(ENOMEM); + } + vt->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_trackfile_resource_init(&vt->resources[vt->resource_count]); + ret = fill_trackfile_resource(resource_elem, + &vt->resources[vt->resource_count], + cpl); + vt->resource_count++; + if (ret) { + av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + continue; + } + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return ret; +} + +static int push_main_image_2d_sequence(xmlNodePtr image_sequence_elem, FFIMFCPL *cpl) +{ + int ret = 0; + uint8_t uuid[16]; + xmlNodePtr resource_list_elem = NULL; + xmlNodePtr resource_elem = NULL; + xmlNodePtr track_id_elem = NULL; + void *tmp; + unsigned long resource_elem_count; + + /* skip stereoscopic resources */ + if (has_stereo_resources(image_sequence_elem)) { + av_log(NULL, AV_LOG_ERROR, "Stereoscopic 3D image virtual tracks not supported\n"); + return AVERROR_PATCHWELCOME; + } + + /* read TrackId element*/ + if (!(track_id_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "TrackId"))) { + av_log(NULL, AV_LOG_ERROR, "TrackId element missing from audio sequence\n"); + return AVERROR_INVALIDDATA; + } + if ((ret = ff_imf_xml_read_uuid(track_id_elem, uuid))) { + av_log(NULL, AV_LOG_ERROR, "Invalid TrackId element found in audio sequence\n"); + return ret; + } + + /* create main image virtual track if one does not exist */ + if (!cpl->main_image_2d_track) { + cpl->main_image_2d_track = av_malloc(sizeof(FFIMFTrackFileVirtualTrack)); + 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)); + + } else if (memcmp(cpl->main_image_2d_track->base.id_uuid, uuid, sizeof(uuid)) != 0) { + 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)); + + /* process resources */ + resource_list_elem = ff_imf_xml_get_child_element_by_name(image_sequence_elem, "ResourceList"); + if (!resource_list_elem) + return 0; + + resource_elem_count = xmlChildElementCount(resource_list_elem); + if (resource_elem_count > UINT32_MAX + || cpl->main_image_2d_track->resource_count > UINT32_MAX - resource_elem_count + || (cpl->main_image_2d_track->resource_count + resource_elem_count) + > INT_MAX / sizeof(FFIMFTrackFileResource)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(cpl->main_image_2d_track->resources, + &cpl->main_image_2d_track->resources_alloc_sz, + (cpl->main_image_2d_track->resource_count + resource_elem_count) + * sizeof(FFIMFTrackFileResource)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate Main Image Resources\n"); + return AVERROR(ENOMEM); + } + cpl->main_image_2d_track->resources = tmp; + + resource_elem = xmlFirstElementChild(resource_list_elem); + while (resource_elem) { + imf_trackfile_resource_init( + &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count]); + ret = fill_trackfile_resource(resource_elem, + &cpl->main_image_2d_track->resources[cpl->main_image_2d_track->resource_count], + cpl); + cpl->main_image_2d_track->resource_count++; + if (ret) { + av_log(NULL, AV_LOG_ERROR, "Invalid Resource\n"); + continue; + } + + resource_elem = xmlNextElementSibling(resource_elem); + } + + return 0; +} + +static int fill_virtual_tracks(xmlNodePtr cpl_element, FFIMFCPL *cpl) +{ + int ret = 0; + xmlNodePtr segment_list_elem = NULL; + xmlNodePtr segment_elem = NULL; + xmlNodePtr sequence_list_elem = NULL; + xmlNodePtr sequence_elem = NULL; + + if (!(segment_list_elem = ff_imf_xml_get_child_element_by_name(cpl_element, "SegmentList"))) { + av_log(NULL, AV_LOG_ERROR, "SegmentList element missing\n"); + return AVERROR_INVALIDDATA; + } + + /* process sequences */ + segment_elem = xmlFirstElementChild(segment_list_elem); + while (segment_elem) { + av_log(NULL, AV_LOG_DEBUG, "Processing IMF CPL Segment\n"); + + sequence_list_elem = ff_imf_xml_get_child_element_by_name(segment_elem, "SequenceList"); + if (!segment_list_elem) + continue; + + sequence_elem = xmlFirstElementChild(sequence_list_elem); + while (sequence_elem) { + if (xmlStrcmp(sequence_elem->name, "MarkerSequence") == 0) + ret = push_marker_sequence(sequence_elem, cpl); + + else if (xmlStrcmp(sequence_elem->name, "MainImageSequence") == 0) + ret = push_main_image_2d_sequence(sequence_elem, cpl); + + else if (xmlStrcmp(sequence_elem->name, "MainAudioSequence") == 0) + ret = push_main_audio_sequence(sequence_elem, cpl); + + else + av_log(NULL, + AV_LOG_INFO, + "The following Sequence is not supported and is ignored: %s\n", + sequence_elem->name); + + /* abort parsing only if memory error occurred */ + if (ret == AVERROR(ENOMEM)) + return ret; + + sequence_elem = xmlNextElementSibling(sequence_elem); + } + + segment_elem = xmlNextElementSibling(segment_elem); + } + + return ret; +} + +int ff_imf_parse_cpl_from_xml_dom(xmlDocPtr doc, FFIMFCPL **cpl) +{ + int ret = 0; + xmlNodePtr cpl_element = NULL; + + *cpl = ff_imf_cpl_alloc(); + if (!*cpl) { + ret = AVERROR(ENOMEM); + goto cleanup; + } + + cpl_element = xmlDocGetRootElement(doc); + if (!cpl_element || xmlStrcmp(cpl_element->name, "CompositionPlaylist")) { + av_log(NULL, AV_LOG_ERROR, "The root element of the CPL is not CompositionPlaylist\n"); + ret = AVERROR_INVALIDDATA; + goto cleanup; + } + + if ((ret = fill_content_title(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_id(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_edit_rate(cpl_element, *cpl))) + goto cleanup; + if ((ret = fill_virtual_tracks(cpl_element, *cpl))) + goto cleanup; + +cleanup: + if (*cpl && ret) { + ff_imf_cpl_free(*cpl); + *cpl = NULL; + } + return ret; +} + +static void imf_marker_free(FFIMFMarker *marker) +{ + if (!marker) + return; + xmlFree(marker->label_utf8); + xmlFree(marker->scope_utf8); +} + +static void imf_marker_resource_free(FFIMFMarkerResource *rsrc) +{ + if (!rsrc) + return; + for (uint32_t i = 0; i < rsrc->marker_count; i++) + imf_marker_free(&rsrc->markers[i]); + av_freep(&rsrc->markers); +} + +static void imf_marker_virtual_track_free(FFIMFMarkerVirtualTrack *vt) +{ + if (!vt) + return; + for (uint32_t i = 0; i < vt->resource_count; i++) + imf_marker_resource_free(&vt->resources[i]); + av_freep(&vt->resources); +} + +static void imf_trackfile_virtual_track_free(FFIMFTrackFileVirtualTrack *vt) +{ + if (!vt) + return; + av_freep(&vt->resources); +} + +static void imf_cpl_init(FFIMFCPL *cpl) +{ + memset(cpl->id_uuid, 0, sizeof(cpl->id_uuid)); + cpl->content_title_utf8 = NULL; + cpl->edit_rate = av_make_q(0, 1); + cpl->main_markers_track = NULL; + cpl->main_image_2d_track = NULL; + cpl->main_audio_track_count = 0; + cpl->main_audio_tracks = NULL; +} + +FFIMFCPL *ff_imf_cpl_alloc(void) +{ + FFIMFCPL *cpl; + + cpl = av_malloc(sizeof(FFIMFCPL)); + if (!cpl) + return NULL; + imf_cpl_init(cpl); + return cpl; +} + +void ff_imf_cpl_free(FFIMFCPL *cpl) +{ + if (!cpl) + return; + + xmlFree(cpl->content_title_utf8); + + imf_marker_virtual_track_free(cpl->main_markers_track); + + if (cpl->main_markers_track) + av_freep(&cpl->main_markers_track); + + imf_trackfile_virtual_track_free(cpl->main_image_2d_track); + + if (cpl->main_image_2d_track) + av_freep(&cpl->main_image_2d_track); + + for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) + imf_trackfile_virtual_track_free(&cpl->main_audio_tracks[i]); + + if (cpl->main_audio_tracks) + av_freep(&cpl->main_audio_tracks); + + av_freep(&cpl); +} + +int ff_imf_parse_cpl(AVIOContext *in, FFIMFCPL **cpl) +{ + AVBPrint buf; + xmlDoc *doc = NULL; + int ret = 0; + int64_t filesize = 0; + + filesize = avio_size(in); + filesize = filesize > 0 ? filesize : 8192; + av_bprint_init(&buf, filesize + 1, AV_BPRINT_SIZE_UNLIMITED); + ret = avio_read_to_bprint(in, &buf, UINT_MAX - 1); + if (ret < 0 || !avio_feof(in) || buf.len == 0) { + av_log(NULL, AV_LOG_ERROR, "Cannot read IMF CPL\n"); + if (ret == 0) + ret = AVERROR_INVALIDDATA; + goto clean_up; + } + + LIBXML_TEST_VERSION + + filesize = buf.len; + doc = xmlReadMemory(buf.str, filesize, NULL, NULL, 0); + if (!doc) { + av_log(NULL, + AV_LOG_ERROR, + "XML parsing failed when reading the IMF CPL\n"); + ret = AVERROR_INVALIDDATA; + goto clean_up; + } + + if ((ret = ff_imf_parse_cpl_from_xml_dom(doc, cpl))) { + av_log(NULL, AV_LOG_ERROR, "Cannot parse IMF CPL\n"); + } else { + av_log(NULL, + AV_LOG_INFO, + "IMF CPL ContentTitle: %s\n", + (*cpl)->content_title_utf8); + av_log(NULL, + AV_LOG_INFO, + "IMF CPL Id: " FF_IMF_UUID_FORMAT "\n", + UID_ARG((*cpl)->id_uuid)); + } + + xmlFreeDoc(doc); + +clean_up: + av_bprint_finalize(&buf, NULL); + + return ret; +} diff --git a/libavformat/imfdec.c b/libavformat/imfdec.c new file mode 100644 index 0000000000..566a0fb792 --- /dev/null +++ b/libavformat/imfdec.c @@ -0,0 +1,895 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) Sandflow Consulting LLC + * + * 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Demuxes an IMF Composition + * + * References + * OV 2067-0:2018 - SMPTE Overview Document - Interoperable Master Format + * ST 2067-2:2020 - SMPTE Standard - Interoperable Master Format — Core Constraints + * ST 2067-3:2020 - SMPTE Standard - Interoperable Master Format — Composition Playlist + * ST 2067-5:2020 - SMPTE Standard - Interoperable Master Format — Essence Component + * ST 2067-20:2016 - SMPTE Standard - Interoperable Master Format — Application #2 + * ST 2067-21:2020 - SMPTE Standard - Interoperable Master Format — Application #2 Extended + * ST 2067-102:2017 - SMPTE Standard - Interoperable Master Format — Common Image Pixel Color Schemes + * ST 429-9:2007 - SMPTE Standard - D-Cinema Packaging — Asset Mapping and File Segmentation + * + * @author Marc-Antoine Arnaud + * @author Valentin Noel + * @author Nicholas Vanderzwet + * @file + * @ingroup lavu_imf + */ + +#include "avio_internal.h" +#include "imf.h" +#include "internal.h" +#include "libavutil/avstring.h" +#include "libavutil/bprint.h" +#include "libavutil/opt.h" +#include "mxf.h" +#include "url.h" +#include +#include + +#define AVRATIONAL_FORMAT "%d/%d" +#define AVRATIONAL_ARG(rational) rational.num, rational.den + +/** + * IMF Asset locator + */ +typedef struct IMFAssetLocator { + FFIMFUUID uuid; + char *absolute_uri; +} IMFAssetLocator; + +/** + * IMF Asset locator map + * Results from the parsing of one or more ASSETMAP XML files + */ +typedef struct IMFAssetLocatorMap { + uint32_t asset_count; + IMFAssetLocator *assets; +} IMFAssetLocatorMap; + +typedef struct IMFVirtualTrackResourcePlaybackCtx { + IMFAssetLocator *locator; + FFIMFTrackFileResource *resource; + AVFormatContext *ctx; +} IMFVirtualTrackResourcePlaybackCtx; + +typedef struct IMFVirtualTrackPlaybackCtx { + int32_t index; /**< Track index in playlist */ + AVRational current_timestamp; /**< Current temporal position */ + AVRational duration; /**< Overall duration */ + uint32_t resource_count; /**< Number of resources */ + unsigned int resources_alloc_sz; /**< Size of the buffer holding the resource */ + IMFVirtualTrackResourcePlaybackCtx *resources; /**< Buffer holding the resources */ + uint32_t current_resource_index; /**< Current resource */ + int64_t last_pts; /**< Last timestamp */ +} IMFVirtualTrackPlaybackCtx; + +typedef struct IMFContext { + const AVClass *class; + const char *base_url; + char *asset_map_paths; + AVIOInterruptCB *interrupt_callback; + AVDictionary *avio_opts; + FFIMFCPL *cpl; + IMFAssetLocatorMap asset_locator_map; + uint32_t track_count; + IMFVirtualTrackPlaybackCtx **tracks; +} IMFContext; + +static int imf_uri_is_url(const char *string) +{ + return strstr(string, "://") != NULL; +} + +static int imf_uri_is_unix_abs_path(const char *string) +{ + return string[0] == '/'; +} + +static int imf_uri_is_dos_abs_path(const char *string) +{ + /* Absolute path case: `C:\path\to\somwhere` */ + if (string[1] == ':' && string[2] == '\\') + return 1; + + /* Absolute path case: `C:/path/to/somwhere` */ + if (string[1] == ':' && string[2] == '/') + return 1; + + /* Network path case: `\\path\to\somwhere` */ + if (string[0] == '\\' && string[1] == '\\') + return 1; + + 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). + * @param doc the XML document to be parsed. + * @param asset_map pointer on the IMFAssetLocatorMap to fill. + * @param base_url the url of the asset map XML file, if any (can be NULL). + * @return a negative value in case of error, 0 otherwise. + */ +static int parse_imf_asset_map_from_xml_dom(AVFormatContext *s, + xmlDocPtr doc, + IMFAssetLocatorMap *asset_map, + const char *base_url) +{ + xmlNodePtr asset_map_element = NULL; + xmlNodePtr node = NULL; + xmlNodePtr asset_element = NULL; + unsigned long elem_count; + char *uri; + int ret = 0; + IMFAssetLocator *asset = NULL; + void *tmp; + + asset_map_element = xmlDocGetRootElement(doc); + + if (!asset_map_element) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing root node\n"); + return AVERROR_INVALIDDATA; + } + + 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); + return AVERROR_INVALIDDATA; + } + + /* parse asset locators */ + if (!(node = ff_imf_xml_get_child_element_by_name(asset_map_element, "AssetList"))) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing AssetList node\n"); + return AVERROR_INVALIDDATA; + } + elem_count = xmlChildElementCount(node); + if (elem_count > UINT32_MAX + || asset_map->asset_count > UINT32_MAX - elem_count) + return AVERROR(ENOMEM); + tmp = av_realloc_array(asset_map->assets, + elem_count + asset_map->asset_count, + sizeof(IMFAssetLocator)); + if (!tmp) { + av_log(NULL, AV_LOG_ERROR, "Cannot allocate IMF asset locators\n"); + return AVERROR(ENOMEM); + } + asset_map->assets = tmp; + + asset_element = xmlFirstElementChild(node); + while (asset_element) { + if (av_strcasecmp(asset_element->name, "Asset") != 0) + continue; + + asset = &(asset_map->assets[asset_map->asset_count]); + + if (ff_imf_xml_read_uuid(ff_imf_xml_get_child_element_by_name(asset_element, "Id"), asset->uuid)) { + av_log(s, AV_LOG_ERROR, "Could not parse UUID from asset in asset map.\n"); + return AVERROR_INVALIDDATA; + } + + av_log(s, AV_LOG_DEBUG, "Found asset id: " FF_IMF_UUID_FORMAT "\n", UID_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"); + return AVERROR_INVALIDDATA; + } + + if (!(node = ff_imf_xml_get_child_element_by_name(node, "Chunk"))) { + av_log(s, AV_LOG_ERROR, "Unable to parse asset map XML - missing Chunk node\n"); + return AVERROR_INVALIDDATA; + } + + uri = xmlNodeGetContent(ff_imf_xml_get_child_element_by_name(node, "Path")); + if (!imf_uri_is_url(uri) && !imf_uri_is_unix_abs_path(uri) && !imf_uri_is_dos_abs_path(uri)) + asset->absolute_uri = av_append_path_component(base_url, uri); + else + asset->absolute_uri = av_strdup(uri); + xmlFree(uri); + if (!asset->absolute_uri) + return AVERROR(ENOMEM); + + av_log(s, AV_LOG_DEBUG, "Found asset absolute URI: %s\n", asset->absolute_uri); + + asset_map->asset_count++; + asset_element = xmlNextElementSibling(asset_element); + } + + return ret; +} + +/** + * Initializes an IMFAssetLocatorMap structure. + */ +static void imf_asset_locator_map_init(IMFAssetLocatorMap *asset_map) +{ + asset_map->assets = NULL; + asset_map->asset_count = 0; +} + +/** + * Free a IMFAssetLocatorMap pointer. + */ +static void imf_asset_locator_map_deinit(IMFAssetLocatorMap *asset_map) +{ + for (uint32_t i = 0; i < asset_map->asset_count; ++i) + av_freep(&asset_map->assets[i].absolute_uri); + + av_freep(&asset_map->assets); +} + +static int parse_assetmap(AVFormatContext *s, const char *url) +{ + IMFContext *c = s->priv_data; + AVIOContext *in = NULL; + struct AVBPrint buf; + AVDictionary *opts = NULL; + xmlDoc *doc = NULL; + const char *base_url; + char *tmp_str = NULL; + int ret; + + av_log(s, AV_LOG_DEBUG, "Asset Map URL: %s\n", url); + + av_dict_copy(&opts, c->avio_opts, 0); + ret = s->io_open(s, &in, url, AVIO_FLAG_READ, &opts); + av_dict_free(&opts); + if (ret < 0) + return ret; + + av_bprint_init(&buf, 0, INT_MAX); // xmlReadMemory uses integer length + + ret = avio_read_to_bprint(in, &buf, SIZE_MAX); + if (ret < 0 || !avio_feof(in)) { + av_log(s, AV_LOG_ERROR, "Unable to read to asset map '%s'\n", url); + if (ret == 0) + ret = AVERROR_INVALIDDATA; + goto clean_up; + } + + LIBXML_TEST_VERSION + + tmp_str = av_strdup(url); + if (!tmp_str) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + base_url = av_dirname(tmp_str); + + doc = xmlReadMemory(buf.str, buf.len, url, NULL, 0); + + 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); + + xmlFreeDoc(doc); + +clean_up: + if (tmp_str) + av_freep(&tmp_str); + ff_format_io_close(s, &in); + av_bprint_finalize(&buf, NULL); + return ret; +} + +static IMFAssetLocator *find_asset_map_locator(IMFAssetLocatorMap *asset_map, FFIMFUUID uuid) +{ + for (uint32_t i = 0; i < asset_map->asset_count; ++i) { + if (memcmp(asset_map->assets[i].uuid, uuid, 16) == 0) + return &(asset_map->assets[i]); + } + return NULL; +} + +static int open_track_resource_context(AVFormatContext *s, + IMFVirtualTrackResourcePlaybackCtx *track_resource) +{ + IMFContext *c = s->priv_data; + int ret = 0; + int64_t entry_point; + AVDictionary *opts = NULL; + + if (track_resource->ctx) { + av_log(s, + AV_LOG_DEBUG, + "Input context already opened for %s.\n", + track_resource->locator->absolute_uri); + return 0; + } + + track_resource->ctx = avformat_alloc_context(); + if (!track_resource->ctx) + return AVERROR(ENOMEM); + + track_resource->ctx->io_open = s->io_open; + track_resource->ctx->io_close = s->io_close; + track_resource->ctx->io_close2 = s->io_close2; + track_resource->ctx->flags |= s->flags & ~AVFMT_FLAG_CUSTOM_IO; + + if ((ret = ff_copy_whiteblacklists(track_resource->ctx, s)) < 0) + goto cleanup; + + if ((ret = av_opt_set(track_resource->ctx, "format_whitelist", "mxf", 0))) + goto cleanup; + + if ((ret = av_dict_copy(&opts, c->avio_opts, 0)) < 0) + goto cleanup; + + ret = avformat_open_input(&track_resource->ctx, + track_resource->locator->absolute_uri, + 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)); + goto cleanup; + } + av_dict_free(&opts); + + /* Compare the source timebase to the resource edit rate, + * considering the first stream of the source file + */ + if (av_cmp_q(track_resource->ctx->streams[0]->time_base, + av_inv_q(track_resource->resource->base.edit_rate))) + av_log(s, + AV_LOG_WARNING, + "Incoherent source stream timebase %d/%d regarding resource edit rate: %d/%d", + track_resource->ctx->streams[0]->time_base.num, + track_resource->ctx->streams[0]->time_base.den, + track_resource->resource->base.edit_rate.den, + track_resource->resource->base.edit_rate.num); + + entry_point = (int64_t)track_resource->resource->base.entry_point + * track_resource->resource->base.edit_rate.den + * AV_TIME_BASE + / track_resource->resource->base.edit_rate.num; + + 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, -1, entry_point, entry_point, entry_point, 0); + if (ret < 0) { + av_log(s, + AV_LOG_ERROR, + "Could not seek at %" PRId64 "on %s: %s\n", + entry_point, + track_resource->locator->absolute_uri, + av_err2str(ret)); + avformat_close_input(&track_resource->ctx); + return ret; + } + } + + return 0; + +cleanup: + av_dict_free(&opts); + avformat_free_context(track_resource->ctx); + track_resource->ctx = NULL; + return ret; +} + +static int open_track_file_resource(AVFormatContext *s, + FFIMFTrackFileResource *track_file_resource, + IMFVirtualTrackPlaybackCtx *track) +{ + IMFContext *c = s->priv_data; + IMFAssetLocator *asset_locator; + void *tmp; + int ret; + + 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)); + return AVERROR_INVALIDDATA; + } + + av_log(s, + AV_LOG_DEBUG, + "Found locator for " FF_IMF_UUID_FORMAT ": %s\n", + UID_ARG(asset_locator->uuid), + asset_locator->absolute_uri); + + if (track->resource_count > UINT32_MAX - track_file_resource->base.repeat_count + || (track->resource_count + track_file_resource->base.repeat_count) + > INT_MAX / sizeof(IMFVirtualTrackResourcePlaybackCtx)) + return AVERROR(ENOMEM); + tmp = av_fast_realloc(track->resources, + &track->resources_alloc_sz, + (track->resource_count + track_file_resource->base.repeat_count) + * sizeof(IMFVirtualTrackResourcePlaybackCtx)); + if (!tmp) + return AVERROR(ENOMEM); + track->resources = tmp; + + for (uint32_t i = 0; i < track_file_resource->base.repeat_count; ++i) { + IMFVirtualTrackResourcePlaybackCtx vt_ctx; + + vt_ctx.locator = asset_locator; + vt_ctx.resource = track_file_resource; + vt_ctx.ctx = NULL; + if ((ret = open_track_resource_context(s, &vt_ctx)) != 0) + return ret; + track->resources[track->resource_count++] = vt_ctx; + track->duration = av_add_q(track->duration, + av_make_q((int)track_file_resource->base.duration + * track_file_resource->base.edit_rate.den, + track_file_resource->base.edit_rate.num)); + } + + return 0; +} + +static void imf_virtual_track_playback_context_deinit(IMFVirtualTrackPlaybackCtx *track) +{ + for (uint32_t i = 0; i < track->resource_count; ++i) + avformat_close_input(&track->resources[i].ctx); + + av_freep(&track->resources); +} + +static int open_virtual_track(AVFormatContext *s, + FFIMFTrackFileVirtualTrack *virtual_track, + int32_t track_index) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackPlaybackCtx *track = NULL; + void *tmp; + int ret = 0; + + if (!(track = av_mallocz(sizeof(IMFVirtualTrackPlaybackCtx)))) + return AVERROR(ENOMEM); + track->index = track_index; + track->duration = av_make_q(0, 1); + + 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), + 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)); + goto clean_up; + } + } + + track->current_timestamp = av_make_q(0, track->duration.den); + + if (c->track_count == UINT32_MAX) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + tmp = av_realloc_array(c->tracks, c->track_count + 1, sizeof(IMFVirtualTrackPlaybackCtx *)); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto clean_up; + } + c->tracks = tmp; + c->tracks[c->track_count++] = track; + + return 0; + +clean_up: + imf_virtual_track_playback_context_deinit(track); + av_free(track); + return ret; +} + +static int set_context_streams_from_tracks(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + int ret = 0; + + for (uint32_t i = 0; i < c->track_count; ++i) { + AVStream *asset_stream; + AVStream *first_resource_stream; + + /* Open the first resource of the track to get stream information */ + first_resource_stream = c->tracks[i]->resources[0].ctx->streams[0]; + av_log(s, AV_LOG_DEBUG, "Open the first resource of track %d\n", c->tracks[i]->index); + + /* Copy stream information */ + asset_stream = avformat_new_stream(s, NULL); + if (!asset_stream) { + av_log(s, AV_LOG_ERROR, "Could not create stream\n"); + return AVERROR(ENOMEM); + } + asset_stream->id = i; + ret = avcodec_parameters_copy(asset_stream->codecpar, first_resource_stream->codecpar); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Could not copy stream parameters\n"); + return ret; + } + avpriv_set_pts_info(asset_stream, + first_resource_stream->pts_wrap_bits, + first_resource_stream->time_base.num, + first_resource_stream->time_base.den); + asset_stream->duration = (int64_t)av_q2d(av_mul_q(c->tracks[i]->duration, + av_inv_q(asset_stream->time_base))); + } + + return 0; +} + +static int open_cpl_tracks(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + int32_t track_index = 0; + int ret; + + 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)); + 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)); + return ret; + } + } + + return set_context_streams_from_tracks(s); +} + +static int imf_read_header(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + char *asset_map_path; + char *tmp_str; + int ret = 0; + + c->interrupt_callback = &s->interrupt_callback; + tmp_str = av_strdup(s->url); + if (!tmp_str) + return AVERROR(ENOMEM); + c->base_url = av_strdup(av_dirname(tmp_str)); + av_freep(&tmp_str); + if (!c->base_url) + return AVERROR(ENOMEM); + + if ((ret = ffio_copy_url_options(s->pb, &c->avio_opts)) < 0) + return ret; + + av_log(s, AV_LOG_DEBUG, "start parsing IMF CPL: %s\n", s->url); + + if ((ret = ff_imf_parse_cpl(s->pb, &c->cpl)) < 0) + return ret; + + av_log(s, + AV_LOG_DEBUG, + "parsed IMF CPL: " FF_IMF_UUID_FORMAT "\n", + UID_ARG(c->cpl->id_uuid)); + + if (!c->asset_map_paths) { + c->asset_map_paths = av_append_path_component(c->base_url, "ASSETMAP.xml"); + if (!c->asset_map_paths) { + ret = AVERROR(ENOMEM); + return ret; + } + av_log(s, AV_LOG_DEBUG, "No asset maps provided, using the default ASSETMAP.xml\n"); + } + + /* Parse each asset map XML file */ + imf_asset_locator_map_init(&c->asset_locator_map); + asset_map_path = av_strtok(c->asset_map_paths, ",", &tmp_str); + while (asset_map_path != NULL) { + av_log(s, AV_LOG_DEBUG, "start parsing IMF Asset Map: %s\n", asset_map_path); + + if ((ret = parse_assetmap(s, asset_map_path))) + return ret; + + asset_map_path = av_strtok(NULL, ",", &tmp_str); + } + + av_log(s, AV_LOG_DEBUG, "parsed IMF Asset Maps\n"); + + if ((ret = open_cpl_tracks(s))) + return ret; + + av_log(s, AV_LOG_DEBUG, "parsed IMF package\n"); + + return 0; +} + +static IMFVirtualTrackPlaybackCtx *get_next_track_with_minimum_timestamp(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackPlaybackCtx *track; + + 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 + " to minimum " AVRATIONAL_FORMAT + " (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)); + + if (av_cmp_q(c->tracks[i - 1]->current_timestamp, minimum_timestamp) <= 0) { + track = c->tracks[i - 1]; + minimum_timestamp = track->current_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; +} + +static IMFVirtualTrackResourcePlaybackCtx *get_resource_context_for_timestamp(AVFormatContext *s, + IMFVirtualTrackPlaybackCtx *track) +{ + AVRational edit_unit_duration = av_inv_q(track->resources[0].resource->base.edit_rate); + AVRational cumulated_duration = av_make_q(0, edit_unit_duration.den); + + av_log(s, + AV_LOG_DEBUG, + "Looking for track %d resource for timestamp = %lf / %lf\n", + track->index, + av_q2d(track->current_timestamp), + av_q2d(track->duration)); + for (uint32_t i = 0; i < track->resource_count; ++i) { + cumulated_duration = av_add_q(cumulated_duration, + av_make_q((int)track->resources[i].resource->base.duration + * edit_unit_duration.num, + edit_unit_duration.den)); + + if (av_cmp_q(av_add_q(track->current_timestamp, edit_unit_duration), cumulated_duration) <= 0) { + av_log(s, + AV_LOG_DEBUG, + "Found resource %d in track %d to read for timestamp %lf " + "(on cumulated=%lf): entry=%" PRIu32 + ", duration=%" PRIu32 + ", editrate=" AVRATIONAL_FORMAT + " | edit_unit_duration=%lf\n", + i, + track->index, + av_q2d(track->current_timestamp), + av_q2d(cumulated_duration), + track->resources[i].resource->base.entry_point, + track->resources[i].resource->base.duration, + AVRATIONAL_ARG(track->resources[i].resource->base.edit_rate), + av_q2d(edit_unit_duration)); + + if (track->current_resource_index != i) { + av_log(s, + AV_LOG_DEBUG, + "Switch resource on track %d: re-open context\n", + track->index); + if (open_track_resource_context(s, &(track->resources[i])) != 0) + return NULL; + avformat_close_input(&(track->resources[track->current_resource_index].ctx)); + track->current_resource_index = i; + } + + return &(track->resources[track->current_resource_index]); + } + } + return NULL; +} + +static int imf_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + IMFContext *c = s->priv_data; + IMFVirtualTrackResourcePlaybackCtx *resource_to_read = NULL; + AVRational edit_unit_duration; + int ret = 0; + IMFVirtualTrackPlaybackCtx *track; + FFStream *track_stream; + + track = get_next_track_with_minimum_timestamp(s); + + if (av_cmp_q(track->current_timestamp, track->duration) == 0) + return AVERROR_EOF; + + resource_to_read = get_resource_context_for_timestamp(s, track); + + if (!resource_to_read) { + edit_unit_duration + = av_inv_q(track->resources[track->current_resource_index].resource->base.edit_rate); + + if (av_cmp_q(av_add_q(track->current_timestamp, edit_unit_duration), track->duration) > 0) + return AVERROR_EOF; + + av_log(s, AV_LOG_ERROR, "Could not find IMF track resource to read\n"); + return AVERROR_STREAM_NOT_FOUND; + } + + while (!ff_check_interrupt(c->interrupt_callback) && !ret) { + ret = av_read_frame(resource_to_read->ctx, pkt); + av_log(s, + AV_LOG_DEBUG, + "Got packet: pts=%" PRId64 + ", dts=%" PRId64 + ", duration=%" PRId64 + ", stream_index=%d, pos=%" PRId64 + "\n", + pkt->pts, + pkt->dts, + pkt->duration, + pkt->stream_index, + pkt->pos); + + track_stream = ffstream(s->streams[track->index]); + if (ret >= 0) { + /* Update packet info from track */ + if (pkt->dts < track_stream->cur_dts && track->last_pts > 0) + pkt->dts = track_stream->cur_dts; + + pkt->pts = track->last_pts; + pkt->dts = pkt->dts + - (int64_t)track->resources[track->current_resource_index].resource->base.entry_point; + pkt->stream_index = track->index; + + /* Update track cursors */ + track->current_timestamp + = av_add_q(track->current_timestamp, + av_make_q((int)pkt->duration + * resource_to_read->ctx->streams[0]->time_base.num, + resource_to_read->ctx->streams[0]->time_base.den)); + track->last_pts += pkt->duration; + + return 0; + } else if (ret != AVERROR_EOF) { + av_log(s, + AV_LOG_ERROR, + "Could not get packet from track %d: %s\n", + track->index, + av_err2str(ret)); + return ret; + } + } + + return AVERROR_EOF; +} + +static int imf_close(AVFormatContext *s) +{ + IMFContext *c = s->priv_data; + + av_log(s, AV_LOG_DEBUG, "Close IMF package\n"); + av_dict_free(&c->avio_opts); + av_freep(&c->base_url); + imf_asset_locator_map_deinit(&c->asset_locator_map); + ff_imf_cpl_free(c->cpl); + + for (uint32_t i = 0; i < c->track_count; ++i) { + imf_virtual_track_playback_context_deinit(c->tracks[i]); + av_freep(&c->tracks[i]); + } + + av_freep(&c->tracks); + + return 0; +} + +static int imf_probe(const AVProbeData *p) +{ + if (!strstr(p->buf, "buf, "ContentTitle>")) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static const AVOption imf_options[] = { + { + .name = "assetmaps", + .help = "Comma-separated paths to ASSETMAP files." + "If not specified, the `ASSETMAP.xml` file in the same " + "directory as the CPL is used.", + .offset = offsetof(IMFContext, asset_map_paths), + .type = AV_OPT_TYPE_STRING, + .default_val = {.str = NULL}, + .flags = AV_OPT_FLAG_DECODING_PARAM, + }, + {NULL}, +}; + +static const AVClass imf_class = { + .class_name = "imf", + .item_name = av_default_item_name, + .option = imf_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +const AVInputFormat ff_imf_demuxer = { + .name = "imf", + .long_name = NULL_IF_CONFIG_SMALL("IMF (Interoperable Master Format)"), + .flags = AVFMT_EXPERIMENTAL, + .flags_internal = FF_FMT_INIT_CLEANUP, + .priv_class = &imf_class, + .priv_data_size = sizeof(IMFContext), + .read_probe = imf_probe, + .read_header = imf_read_header, + .read_packet = imf_read_packet, + .read_close = imf_close, +}; diff --git a/libavformat/img2dec.c b/libavformat/img2dec.c index b535831e1c..4d5ac51b53 100644 --- a/libavformat/img2dec.c +++ b/libavformat/img2dec.c @@ -749,7 +749,7 @@ static int j2k_probe(const AVProbeData *p) static int jpeg_probe(const AVProbeData *p) { const uint8_t *b = p->buf; - int i, state = SOI; + int i, state = SOI, got_header = 0; if (AV_RB16(b) != 0xFFD8 || AV_RB32(b) == 0xFFD8FFF7) @@ -789,7 +789,11 @@ static int jpeg_probe(const AVProbeData *p) break; case DQT: case APP0: + if (AV_RL32(&b[i + 4]) == MKTAG('J','F','I','F')) + got_header = 1; case APP1: + if (AV_RL32(&b[i + 4]) == MKTAG('E','x','i','f')) + got_header = 1; case APP2: case APP3: case APP4: @@ -817,7 +821,7 @@ static int jpeg_probe(const AVProbeData *p) if (state == EOI) return AVPROBE_SCORE_EXTENSION + 1; if (state == SOS) - return AVPROBE_SCORE_EXTENSION / 2; + return AVPROBE_SCORE_EXTENSION / 2 + got_header; return AVPROBE_SCORE_EXTENSION / 8 + 1; } @@ -1126,7 +1130,8 @@ static int gem_probe(const AVProbeData *p) return ret; } -#define IMAGEAUTO_DEMUXER(imgname, codecid)\ +#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"),\ @@ -1139,33 +1144,43 @@ 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(pam, PAM) +IMAGEAUTO_DEMUXER(pbm, PBM) +IMAGEAUTO_DEMUXER(pcx, PCX) +IMAGEAUTO_DEMUXER(pgm, PGM) +IMAGEAUTO_DEMUXER(pgmyuv, PGMYUV) +IMAGEAUTO_DEMUXER(pgx, PGX) +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(sgi, SGI) +IMAGEAUTO_DEMUXER(sunrast, SUNRAST) +IMAGEAUTO_DEMUXER(svg, SVG) +IMAGEAUTO_DEMUXER(tiff, TIFF) +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 62202de9f4..ded91d6b98 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -36,7 +36,6 @@ typedef struct VideoMuxData { const AVClass *class; /**< Class for private options. */ int img_number; int split_planes; /**< use independent file for each Y, U, V plane */ - char path[1024]; char tmp[4][1024]; char target[4][1024]; int update; @@ -53,14 +52,12 @@ static int write_header(AVFormatContext *s) AVStream *st = s->streams[0]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(st->codecpar->format); - av_strlcpy(img->path, s->url, sizeof(img->path)); - if (st->codecpar->codec_id == AV_CODEC_ID_GIF) { 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_RAWVIDEO) { - const char *str = strrchr(img->path, '.'); + const char *str = strrchr(s->url, '.'); img->split_planes = str && !av_strcasecmp(str + 1, "y") && s->nb_streams == 1 @@ -124,6 +121,13 @@ static int write_packet_pipe(AVFormatContext *s, AVPacket *pkt) return 0; } +static int write_and_close(AVFormatContext *s, AVIOContext **pb, const unsigned char *buf, int size) +{ + avio_write(*pb, buf, size); + avio_flush(*pb); + return ff_format_io_close(s, pb); +} + static int write_packet(AVFormatContext *s, AVPacket *pkt) { VideoMuxData *img = s->priv_data; @@ -136,29 +140,29 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) AVDictionary *options = NULL; if (img->update) { - av_strlcpy(filename, img->path, sizeof(filename)); + av_strlcpy(filename, s->url, sizeof(filename)); } else if (img->use_strftime) { time_t now0; struct tm *tm, tmpbuf; time(&now0); tm = localtime_r(&now0, &tmpbuf); - if (!strftime(filename, sizeof(filename), img->path, tm)) { + if (!strftime(filename, sizeof(filename), s->url, tm)) { av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } } else if (img->frame_pts) { - if (av_get_frame_filename2(filename, sizeof(filename), img->path, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { + if (av_get_frame_filename2(filename, sizeof(filename), s->url, pkt->pts, AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) { av_log(s, AV_LOG_ERROR, "Cannot write filename by pts of the frames."); return AVERROR(EINVAL); } - } else if (av_get_frame_filename2(filename, sizeof(filename), img->path, + } 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, img->path); + img->img_number, s->url); return AVERROR(EINVAL); } for (i = 0; i < 4; i++) { @@ -190,24 +194,22 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) ysize *= 2; usize *= 2; } - avio_write(pb[0], pkt->data , ysize); - avio_write(pb[1], pkt->data + ysize , usize); - avio_write(pb[2], pkt->data + ysize + usize, usize); - ff_format_io_close(s, &pb[1]); - ff_format_io_close(s, &pb[2]); - if (desc->nb_components > 3) { - avio_write(pb[3], pkt->data + ysize + 2*usize, ysize); - ff_format_io_close(s, &pb[3]); - } - } else if (img->muxer) { - ret = write_muxed_file(s, pb[0], pkt); - if (ret < 0) + if ((ret = write_and_close(s, &pb[0], pkt->data , ysize)) < 0 || + (ret = write_and_close(s, &pb[1], pkt->data + ysize , usize)) < 0 || + (ret = write_and_close(s, &pb[2], pkt->data + ysize + usize, usize)) < 0) goto fail; + if (desc->nb_components > 3) + ret = write_and_close(s, &pb[3], pkt->data + ysize + 2*usize, ysize); + } else if (img->muxer) { + if ((ret = write_muxed_file(s, pb[0], pkt)) < 0) + goto fail; + ret = ff_format_io_close(s, &pb[0]); } else { - avio_write(pb[0], pkt->data, pkt->size); + ret = write_and_close(s, &pb[0], pkt->data, pkt->size); } - avio_flush(pb[0]); - ff_format_io_close(s, &pb[0]); + if (ret < 0) + goto fail; + for (i = 0; i < nb_renames; i++) { int ret = ff_rename(img->tmp[i], img->target[i], s); if (ret < 0) diff --git a/libavformat/internal.h b/libavformat/internal.h index f1ae7db365..bffb8e66ff 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -25,6 +25,7 @@ #include "libavcodec/avcodec.h" #include "libavcodec/bsf.h" +#include "libavcodec/packet_internal.h" #include "avformat.h" #include "os_support.h" @@ -81,13 +82,18 @@ typedef struct FFFormatContext { */ int nb_interleaved_streams; + /** + * The interleavement function in use. Always set for muxers. + */ + int (*interleave_packet)(struct AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet); + /** * This buffer is only needed when packets were already buffered but * not decoded, for example to get the codec parameters in MPEG * streams. */ - struct PacketList *packet_buffer; - struct PacketList *packet_buffer_end; + PacketList packet_buffer; /* av_seek_frame() support */ int64_t data_offset; /**< offset of the first packet */ @@ -98,13 +104,11 @@ typedef struct FFFormatContext { * be identified, as parsing cannot be done without knowing the * codec. */ - struct PacketList *raw_packet_buffer; - struct PacketList *raw_packet_buffer_end; + PacketList raw_packet_buffer; /** * Packets split by the parser get queued here. */ - struct PacketList *parse_queue; - struct PacketList *parse_queue_end; + PacketList parse_queue; /** * The generic code uses this as a temporary packet * to parse packets or for muxing, especially flushing. @@ -127,10 +131,9 @@ typedef struct FFFormatContext { */ AVPacket *pkt; /** - * Remaining size available for raw_packet_buffer, in bytes. + * Sum of the size of packets in raw_packet_buffer, in bytes. */ -#define RAW_PACKET_BUFFER_SIZE 2500000 - int raw_packet_buffer_remaining_size; + int raw_packet_buffer_size; /** * Offset to remap timestamps to be non-negative. @@ -388,7 +391,7 @@ typedef struct FFStream { /** * last packet in packet_buffer for this stream when muxing. */ - struct PacketList *last_in_packet_buffer; + PacketListEntry *last_in_packet_buffer; int64_t last_IP_pts; int last_IP_duration; @@ -479,6 +482,17 @@ void ff_flush_packet_queue(AVFormatContext *s); */ int ff_mkdir_p(const char *path); +/** + * Write hexadecimal string corresponding to given binary data. The string + * is zero-terminated. + * + * @param buf the output string is written here; + * needs to be at least 2 * size + 1 bytes long. + * @param src the input data to be transformed. + * @param size the size (in byte) of src. + * @param lowercase determines whether to use the range [0-9a-f] or [0-9A-F]. + * @return buf. + */ char *ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase); /** @@ -540,10 +554,11 @@ uint64_t ff_parse_ntp_time(uint64_t ntp_ts); * @param ttl the time to live of the stream, 0 if not multicast * @param fmt the AVFormatContext, which might contain options modifying * the generated SDP + * @return 0 on success, a negative error code on failure */ -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt); +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 @@ -614,7 +629,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, * Find stream index based on format-specific stream ID * @return stream index, or < 0 on error */ -int ff_find_stream_index(AVFormatContext *s, int id); +int ff_find_stream_index(const AVFormatContext *s, int id); /** * Internal version of av_index_search_timestamp @@ -754,6 +769,13 @@ int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, 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); unsigned int ff_codec_get_tag(const AVCodecTag *tags, enum AVCodecID id); @@ -817,6 +839,15 @@ int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *a */ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src); +/** + * Copy side data 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_side_data_copy(AVStream *dst, const AVStream *src); + /** * Wrap ffurl_move() and log if error happens. * @@ -893,8 +924,16 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op /* * A wrapper around AVFormatContext.io_close that should be used * instead of calling the pointer directly. + * + * @param s AVFormatContext + * @param *pb the AVIOContext to be closed and freed. Can be NULL. + * @return >=0 on success, negative AVERROR in case of failure */ -void ff_format_io_close(AVFormatContext *s, AVIOContext **pb); +int ff_format_io_close(AVFormatContext *s, AVIOContext **pb); + +/* Default io_close callback, not to be used directly, use ff_format_io_close + * instead. */ +void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb); /** * Utility function to check if the file uses http or https protocol @@ -978,4 +1017,11 @@ 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/isom.c b/libavformat/isom.c index 300ba927c2..015c82e1bb 100644 --- a/libavformat/isom.c +++ b/libavformat/isom.c @@ -362,7 +362,7 @@ int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext return ret; st->codecpar->channels = cfg.channels; if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 - st->codecpar->sample_rate = avpriv_mpa_freq_tab[cfg.sampling_index]; + st->codecpar->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; else if (cfg.ext_sample_rate) st->codecpar->sample_rate = cfg.ext_sample_rate; else diff --git a/libavformat/isom.h b/libavformat/isom.h index f3c18c95be..625dea8421 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -55,9 +55,14 @@ struct AVAESCTR; typedef struct MOVStts { unsigned int count; - int duration; + unsigned int duration; } MOVStts; +typedef struct MOVCtts { + unsigned int count; + int duration; +} MOVCtts; + typedef struct MOVStsc { int first; int count; @@ -168,7 +173,7 @@ typedef struct MOVStreamContext { uint8_t *sdtp_data; unsigned int ctts_count; unsigned int ctts_allocated_size; - MOVStts *ctts_data; + MOVCtts *ctts_data; unsigned int stsc_count; MOVStsc *stsc_data; unsigned int stsc_index; @@ -300,6 +305,7 @@ typedef struct MOVContext { int32_t movie_display_matrix[3][3]; ///< display matrix from mvhd int have_read_mfra_size; uint32_t mfra_size; + uint32_t max_stts_delta; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/libavformat/isom_tags.c b/libavformat/isom_tags.c index d0400b18fc..62e60470a8 100644 --- a/libavformat/isom_tags.c +++ b/libavformat/isom_tags.c @@ -312,10 +312,10 @@ const AVCodecTag ff_codec_movaudio_tags[] = { { AV_CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, { AV_CODEC_ID_PCM_S16BE, MKTAG('l', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S16LE, MKTAG('l', 'p', 'c', 'm') }, + { AV_CODEC_ID_PCM_S16BE, MKTAG('i', 'p', 'c', 'm') }, + { AV_CODEC_ID_PCM_S16LE, MKTAG('i', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') }, { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'n', '2', '4') }, - { AV_CODEC_ID_PCM_S24BE, MKTAG('i', 'p', 'c', 'm') }, - { AV_CODEC_ID_PCM_S24LE, MKTAG('i', 'p', 'c', 'm') }, { AV_CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') }, { AV_CODEC_ID_PCM_S32LE, MKTAG('i', 'n', '3', '2') }, { AV_CODEC_ID_PCM_S8, MKTAG('s', 'o', 'w', 't') }, diff --git a/libavformat/jpegtables.c b/libavformat/jpegtables.c new file mode 100644 index 0000000000..57eae9f9a6 --- /dev/null +++ b/libavformat/jpegtables.c @@ -0,0 +1,24 @@ +/* + * MJPEG tables + * Copyright (c) 2000, 2001 Fabrice Bellard + * Copyright (c) 2003 Alex Beregszaszi + * Copyright (c) 2003-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 "libavcodec/jpegtabs.h" diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index 21bb614f67..72865c9565 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -245,10 +245,10 @@ too_large: return AVERROR_INVALIDDATA; } -static int latm_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int latm_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/librist.c b/libavformat/librist.c index 6eae90cc2f..378b635ea7 100644 --- a/libavformat/librist.c +++ b/libavformat/librist.c @@ -130,6 +130,7 @@ static int librist_open(URLContext *h, const char *uri, int flags) if ((flags & AVIO_FLAG_READ_WRITE) == AVIO_FLAG_READ_WRITE) return AVERROR(EINVAL); + s->logging_settings = (struct rist_logging_settings)LOGGING_SETTINGS_INITIALIZER; ret = rist_logging_set(&logging_settings, s->log_level, log_cb, h, NULL, NULL); if (ret < 0) return risterr2ret(ret); diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c index 145eea2f7c..19b9cb9895 100644 --- a/libavformat/libsrt.c +++ b/libavformat/libsrt.c @@ -320,7 +320,9 @@ static int libsrt_set_options_pre(URLContext *h, int fd) int latency = s->latency / 1000; int rcvlatency = s->rcvlatency / 1000; int peerlatency = s->peerlatency / 1000; +#if SRT_VERSION_VALUE >= 0x010302 int snddropdelay = s->snddropdelay > 0 ? s->snddropdelay / 1000 : s->snddropdelay; +#endif int connect_timeout = s->connect_timeout; if ((s->mode == SRT_MODE_RENDEZVOUS && libsrt_setsockopt(h, fd, SRTO_RENDEZVOUS, "SRTO_RENDEZVOUS", &yes, sizeof(yes)) < 0) || diff --git a/libavformat/matroska.h b/libavformat/matroska.h index 2d04a6838b..16491aae22 100644 --- a/libavformat/matroska.h +++ b/libavformat/matroska.h @@ -111,6 +111,7 @@ #define MATROSKA_ID_TRACKCONTENTENCODING 0x6240 #define MATROSKA_ID_TRACKTIMECODESCALE 0x23314F #define MATROSKA_ID_TRACKMAXBLKADDID 0x55EE +#define MATROSKA_ID_TRACKBLKADDMAPPING 0x41E4 /* IDs in the trackvideo master */ #define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 @@ -189,6 +190,12 @@ #define MATROSKA_ID_ENCODINGSIGKEYID 0x47E4 #define MATROSKA_ID_ENCODINGSIGNATURE 0x47E3 +/* IDs in the block addition mapping master */ +#define MATROSKA_ID_BLKADDIDVALUE 0x41F0 +#define MATROSKA_ID_BLKADDIDNAME 0x41A4 +#define MATROSKA_ID_BLKADDIDTYPE 0x41E7 +#define MATROSKA_ID_BLKADDIDEXTRADATA 0x41ED + /* ID in the cues master */ #define MATROSKA_ID_POINTENTRY 0xBB @@ -385,4 +392,6 @@ extern const char * const ff_matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_P int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); +#define DVCC_DVVC_BLOCK_TYPE_NAME "Dolby Vision configuration" + #endif /* AVFORMAT_MATROSKA_H */ diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index b2c4927e43..78e5a4a203 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -53,6 +53,7 @@ #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "internal.h" #include "isom.h" #include "matroska.h" @@ -239,6 +240,13 @@ typedef struct MatroskaTrackOperation { EbmlList combine_planes; } MatroskaTrackOperation; +typedef struct MatroskaBlockAdditionMapping { + uint64_t value; + char *name; + uint64_t type; + EbmlBin extradata; +} MatroskaBlockAdditionMapping; + typedef struct MatroskaTrack { uint64_t num; uint64_t uid; @@ -269,6 +277,7 @@ typedef struct MatroskaTrack { int ms_compat; int needs_decoding; uint64_t max_block_additional_id; + EbmlList block_addition_mappings; uint32_t palette[AVPALETTE_COUNT]; int has_palette; @@ -387,8 +396,7 @@ typedef struct MatroskaDemuxContext { AVPacket *pkt; /* the packet queue */ - PacketList *queue; - PacketList *queue_end; + PacketList queue; int done; @@ -419,8 +427,8 @@ typedef struct MatroskaDemuxContext { // incomplete type (6.7.2 in C90, 6.9.2 in C99). // Removing the sizes breaks MSVC. static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], - matroska_track[32], matroska_track_encoding[6], matroska_track_encodings[2], - matroska_track_combine_planes[2], matroska_track_operation[2], matroska_tracks[2], + matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; @@ -570,6 +578,14 @@ static EbmlSyntax matroska_track_operation[] = { CHILD_OF(matroska_track) }; +static EbmlSyntax matroska_block_addition_mapping[] = { + { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, + { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, + { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type) }, + { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, + CHILD_OF(matroska_track) +}; + static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, @@ -593,6 +609,7 @@ static EbmlSyntax matroska_track[] = { { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id), { .u = 0 } }, + { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll), { .u = 0 } }, { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, @@ -2011,8 +2028,8 @@ static int matroska_aac_sri(int samplerate) { int sri; - for (sri = 0; sri < FF_ARRAY_ELEMS(avpriv_mpeg4audio_sample_rates); sri++) - if (avpriv_mpeg4audio_sample_rates[sri] == samplerate) + for (sri = 0; sri < FF_ARRAY_ELEMS(ff_mpeg4audio_sample_rates); sri++) + if (ff_mpeg4audio_sample_rates[sri] == samplerate) break; return sri; } @@ -2311,6 +2328,38 @@ static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, return 0; } +static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaTrack *track, + EbmlBin *bin) +{ + return ff_isom_parse_dvcc_dvvc(s, st, bin->data, bin->size); +} + +static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, const MatroskaTrack *track) +{ + const EbmlList *mappings_list = &track->block_addition_mappings; + MatroskaBlockAdditionMapping *mappings = mappings_list->elem; + int ret; + + for (int i = 0; i < mappings_list->nb_elem; i++) { + MatroskaBlockAdditionMapping *mapping = &mappings[i]; + + switch (mapping->type) { + case MKBETAG('d','v','c','C'): + case MKBETAG('d','v','v','C'): + if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) + return ret; + + break; + default: + av_log(s, AV_LOG_DEBUG, + "Unknown block additional mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", + mapping->type, mapping->value, mapping->name ? mapping->name : ""); + } + } + + return 0; +} + static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id) { const AVCodecTag *codec_tags; @@ -2806,7 +2855,7 @@ static int matroska_parse_tracks(AVFormatContext *s) &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, - 255); + INT_MAX); } if (st->codecpar->codec_id != AV_CODEC_ID_HEVC) sti->need_parsing = AVSTREAM_PARSE_HEADERS; @@ -2898,6 +2947,10 @@ static int matroska_parse_tracks(AVFormatContext *s) if (track->flag_textdescriptions) st->disposition |= AV_DISPOSITION_DESCRIPTIONS; } + + ret = mkv_parse_block_addition_mappings(s, st, track); + if (ret < 0) + return ret; } return 0; @@ -3058,11 +3111,11 @@ static int matroska_read_header(AVFormatContext *s) static int matroska_deliver_packet(MatroskaDemuxContext *matroska, AVPacket *pkt) { - if (matroska->queue) { + if (matroska->queue.head) { MatroskaTrack *tracks = matroska->tracks.elem; MatroskaTrack *track; - avpriv_packet_list_get(&matroska->queue, &matroska->queue_end, pkt); + avpriv_packet_list_get(&matroska->queue, pkt); track = &tracks[pkt->stream_index]; if (track->has_palette) { uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); @@ -3084,7 +3137,7 @@ static int matroska_deliver_packet(MatroskaDemuxContext *matroska, */ static void matroska_clear_queue(MatroskaDemuxContext *matroska) { - avpriv_packet_list_free(&matroska->queue, &matroska->queue_end); + avpriv_packet_list_free(&matroska->queue); } static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, @@ -3250,7 +3303,7 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, track->audio.buf_timecode = AV_NOPTS_VALUE; pkt->pos = pos; pkt->stream_index = st->index; - ret = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + ret = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (ret < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3472,7 +3525,7 @@ static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, pkt->duration = duration; pkt->pos = pos; - err = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + err = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (err < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3574,7 +3627,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, pkt->pos = pos; pkt->duration = lace_duration; - res = avpriv_packet_list_put(&matroska->queue, &matroska->queue_end, pkt, NULL, 0); + res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); if (res < 0) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -3976,10 +4029,10 @@ static int webm_clusters_start_with_keyframe(AVFormatContext *s) matroska_reset_status(matroska, 0, cluster_pos); matroska_clear_queue(matroska); if (matroska_parse_cluster(matroska) < 0 || - !matroska->queue) { + !matroska->queue.head) { break; } - pkt = &matroska->queue->pkt; + pkt = &matroska->queue.head->pkt; // 4 + read is the length of the cluster id and the cluster length field. cluster_pos += 4 + read + cluster_length; if (!(pkt->flags & AV_PKT_FLAG_KEY)) { diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 6945c26f5a..41b2df7dbf 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -21,12 +21,15 @@ #include +#include "config.h" + #include "av1.h" #include "avc.h" #include "hevc.h" #include "avformat.h" #include "avio_internal.h" #include "avlanguage.h" +#include "dovi_isom.h" #include "flacenc.h" #include "internal.h" #include "isom.h" @@ -58,6 +61,11 @@ * Info, Tracks, Chapters, Attachments, Tags (potentially twice) and Cues */ #define MAX_SEEKHEAD_ENTRIES 7 +#define MODE_MATROSKAv2 0x01 +#define MODE_WEBM 0x02 + +#define IS_WEBM(mkv) (CONFIG_WEBM_MUXER && CONFIG_MATROSKA_MUXER ? \ + ((mkv)->mode == MODE_WEBM) : CONFIG_WEBM_MUXER) #define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \ !(mkv)->is_live) @@ -117,9 +125,6 @@ typedef struct mkv_track { int64_t ts_offset; } mkv_track; -#define MODE_MATROSKAv2 0x01 -#define MODE_WEBM 0x02 - typedef struct MatroskaMuxContext { const AVClass *class; int mode; @@ -156,6 +161,7 @@ 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; @@ -533,6 +539,7 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, { mkv_cues *cues = &mkv->cues; mkv_cuepoint *entries = cues->entries; + unsigned idx = cues->num_entries; if (ts < 0) return 0; @@ -542,17 +549,26 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int64_t ts, return AVERROR(ENOMEM); cues->entries = entries; - cues->entries[cues->num_entries].pts = ts; - cues->entries[cues->num_entries].stream_idx = stream; - cues->entries[cues->num_entries].cluster_pos = cluster_pos - mkv->segment_offset; - cues->entries[cues->num_entries].relative_pos = relative_pos; - cues->entries[cues->num_entries++].duration = duration; + /* Make sure the cues entries are sorted by pts. */ + while (idx > 0 && entries[idx - 1].pts > ts) + idx--; + memmove(&entries[idx + 1], &entries[idx], + (cues->num_entries - idx) * sizeof(entries[0])); + + entries[idx].pts = ts; + entries[idx].stream_idx = stream; + entries[idx].cluster_pos = cluster_pos - mkv->segment_offset; + entries[idx].relative_pos = relative_pos; + entries[idx].duration = duration; + + cues->num_entries++; return 0; } static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, - mkv_cues *cues, mkv_track *tracks, int num_tracks) + const mkv_cues *cues, mkv_track *tracks, int num_tracks, + uint64_t offset) { AVIOContext *cuepoint; int ret; @@ -583,7 +599,7 @@ 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); @@ -630,6 +646,7 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, return 0; } +#if CONFIG_MATROSKA_MUXER static int put_wv_codecpriv(AVIOContext *pb, const AVCodecParameters *par) { if (par->extradata && par->extradata_size == 2) @@ -707,6 +724,7 @@ static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv, } return 0; } +#endif static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, const AVCodecParameters *par, @@ -716,6 +734,14 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, case AV_CODEC_ID_VORBIS: case AV_CODEC_ID_THEORA: return put_xiph_codecpriv(s, dyn_cp, par); + case AV_CODEC_ID_AV1: + if (par->extradata_size) + return ff_isom_write_av1c(dyn_cp, par->extradata, + par->extradata_size); + else + put_ebml_void(pb, 4 + 3); + break; +#if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_FLAC: return put_flac_codecpriv(s, dyn_cp, par); case AV_CODEC_ID_WAVPACK: @@ -726,13 +752,6 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, case AV_CODEC_ID_HEVC: return ff_isom_write_hvcc(dyn_cp, par->extradata, par->extradata_size, 0); - case AV_CODEC_ID_AV1: - if (par->extradata_size) - return ff_isom_write_av1c(dyn_cp, par->extradata, - par->extradata_size); - else - put_ebml_void(pb, 4 + 3); - break; case AV_CODEC_ID_ALAC: if (par->extradata_size < 36) { av_log(s, AV_LOG_ERROR, @@ -749,8 +768,9 @@ static int mkv_write_native_codecprivate(AVFormatContext *s, AVIOContext *pb, else put_ebml_void(pb, MAX_PCE_SIZE + 2 + 4); break; +#endif default: - if (par->codec_id == AV_CODEC_ID_PRORES && + 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) @@ -764,8 +784,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par, int native_id, int qt_id) { + MatroskaMuxContext av_unused *const mkv = s->priv_data; AVIOContext *dyn_cp; - MatroskaMuxContext *mkv = s->priv_data; uint8_t *codecpriv; int ret, codecpriv_size; @@ -775,6 +795,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, if (native_id) { ret = mkv_write_native_codecprivate(s, pb, par, dyn_cp); +#if CONFIG_MATROSKA_MUXER } else if (par->codec_type == AVMEDIA_TYPE_VIDEO) { if (qt_id) { if (!par->codec_tag) @@ -816,6 +837,7 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, par->codec_tag = tag; ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); +#endif } if (ret >= 0) { @@ -981,7 +1003,7 @@ static void mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, end_ebml_master(pb, projection); } -static void mkv_write_field_order(AVIOContext *pb, int mode, +static void mkv_write_field_order(AVIOContext *pb, int is_webm, enum AVFieldOrder field_order) { switch (field_order) { @@ -997,7 +1019,7 @@ static void mkv_write_field_order(AVIOContext *pb, int mode, case AV_FIELD_BT: put_ebml_uint(pb, MATROSKA_ID_VIDEOFLAGINTERLACED, MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED); - if (mode != MODE_WEBM) { + if (!is_webm) { switch (field_order) { case AV_FIELD_TT: put_ebml_uint(pb, MATROSKA_ID_VIDEOFIELDORDER, @@ -1021,7 +1043,8 @@ static void mkv_write_field_order(AVIOContext *pb, int mode, } static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, - AVStream *st, int mode, int *h_width, int *h_height) + AVStream *st, int is_webm, + int *h_width, int *h_height) { const AVDictionaryEntry *tag; MatroskaVideoStereoModeType format = MATROSKA_VIDEO_STEREOMODE_TYPE_NB; @@ -1096,7 +1119,7 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; // if webm, do not write unsupported modes - if ((mode == MODE_WEBM && + if ((is_webm && format > MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM && format != MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT) || format >= MATROSKA_VIDEO_STEREOMODE_TYPE_NB) { @@ -1111,6 +1134,39 @@ static int mkv_write_stereo_mode(AVFormatContext *s, AVIOContext *pb, return 0; } +static void mkv_write_dovi(AVFormatContext *s, AVIOContext *pb, AVStream *st) +{ +#if CONFIG_MATROSKA_MUXER + AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *) + av_stream_get_side_data(st, AV_PKT_DATA_DOVI_CONF, NULL); + + if (dovi && dovi->dv_profile <= 10) { + ebml_master mapping; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + uint32_t type; + + uint64_t expected_size = (2 + 1 + (sizeof(DVCC_DVVC_BLOCK_TYPE_NAME) - 1)) + + (2 + 1 + 4) + (2 + 1 + ISOM_DVCC_DVVC_SIZE); + + if (dovi->dv_profile > 7) { + type = MKBETAG('d', 'v', 'v', 'C'); + } else { + type = MKBETAG('d', 'v', 'c', 'C'); + } + + ff_isom_put_dvcc_dvvc(s, buf, dovi); + + mapping = start_ebml_master(pb, MATROSKA_ID_TRACKBLKADDMAPPING, expected_size); + + put_ebml_string(pb, MATROSKA_ID_BLKADDIDNAME, DVCC_DVVC_BLOCK_TYPE_NAME); + put_ebml_uint(pb, MATROSKA_ID_BLKADDIDTYPE, type); + put_ebml_binary(pb, MATROSKA_ID_BLKADDIDEXTRADATA, buf, sizeof(buf)); + + end_ebml_master(pb, mapping); + } +#endif +} + static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, AVStream *st, mkv_track *track, AVIOContext *pb, int is_default) @@ -1130,13 +1186,6 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, if (par->codec_type == AVMEDIA_TYPE_ATTACHMENT) return 0; - if (par->codec_id == AV_CODEC_ID_AAC) { - ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, - &sample_rate, &output_sample_rate); - if (ret < 0) - return ret; - } - track_master = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); put_ebml_uint(pb, MATROSKA_ID_TRACKNUMBER, track->track_num); put_ebml_uid (pb, MATROSKA_ID_TRACKUID, track->uid); @@ -1156,7 +1205,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, if (st->disposition & AV_DISPOSITION_FORCED) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1); - if (mkv->mode == MODE_WEBM) { + if (IS_WEBM(mkv)) { const char *codec_id; if (par->codec_type != AVMEDIA_TYPE_SUBTITLE) { for (j = 0; ff_webm_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { @@ -1235,7 +1284,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, && av_cmp_q(av_inv_q(st->r_frame_rate), st->time_base) > 0) put_ebml_uint(pb, MATROSKA_ID_TRACKDEFAULTDURATION, 1000000000LL * st->r_frame_rate.den / st->r_frame_rate.num); - if (!native_id && + if (CONFIG_MATROSKA_MUXER && !native_id && ff_codec_get_tag(ff_codec_movvideo_tags, par->codec_id) && ((!ff_codec_get_tag(ff_codec_bmp_tags, par->codec_id) && par->codec_id != AV_CODEC_ID_RAWVIDEO) || par->codec_id == AV_CODEC_ID_SVQ1 || @@ -1257,11 +1306,11 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELWIDTH , par->width); put_ebml_uint (pb, MATROSKA_ID_VIDEOPIXELHEIGHT, par->height); - mkv_write_field_order(pb, mkv->mode, par->field_order); + 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, mkv->mode, + ret = mkv_write_stereo_mode(s, pb, st, IS_WEBM(mkv), &display_width_div, &display_height_div); if (ret < 0) @@ -1282,7 +1331,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return AVERROR(EINVAL); } if (d_width != par->width || display_width_div != 1 || display_height_div != 1) { - if (mkv->mode == MODE_WEBM || 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 { @@ -1299,7 +1348,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } 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 (mkv->mode != MODE_WEBM) + } else if (!IS_WEBM(mkv)) put_ebml_uint(pb, MATROSKA_ID_VIDEODISPLAYUNIT, MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN); if (par->codec_id == AV_CODEC_ID_RAWVIDEO) { @@ -1310,6 +1359,10 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, mkv_write_video_projection(s, pb, st); end_ebml_master(pb, subinfo); + + if (!IS_WEBM(mkv)) + mkv_write_dovi(s, pb, st); + break; case AVMEDIA_TYPE_AUDIO: @@ -1329,6 +1382,14 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, } if (par->codec_id == AV_CODEC_ID_OPUS) put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); +#if CONFIG_MATROSKA_MUXER + else if (par->codec_id == AV_CODEC_ID_AAC) { + ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, + &sample_rate, &output_sample_rate); + if (ret < 0) + return ret; + } +#endif put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_AUDIO); @@ -1363,10 +1424,10 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", par->codec_id); return AVERROR(ENOSYS); } - if (mkv->mode != MODE_WEBM && st->disposition & AV_DISPOSITION_DESCRIPTIONS) + if (!IS_WEBM(mkv) && st->disposition & AV_DISPOSITION_DESCRIPTIONS) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, 1); - if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) + if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) native_id = MATROSKA_TRACK_TYPE_SUBTITLE; put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id); @@ -1376,7 +1437,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return AVERROR(EINVAL); } - if (mkv->mode != MODE_WEBM || par->codec_id != AV_CODEC_ID_WEBVTT) { + if (!IS_WEBM(mkv) || par->codec_id != AV_CODEC_ID_WEBVTT) { track->codecpriv_offset = avio_tell(pb); ret = mkv_write_codecprivate(s, pb, par, native_id, qt_id); if (ret < 0) @@ -1595,7 +1656,7 @@ static int mkv_write_tags(AVFormatContext *s) } } - if (mkv->nb_attachments && mkv->mode != MODE_WEBM) { + if (mkv->nb_attachments && !IS_WEBM(mkv)) { for (i = 0; i < s->nb_streams; i++) { const mkv_track *track = &mkv->tracks[i]; const AVStream *st = s->streams[i]; @@ -1648,7 +1709,7 @@ static int mkv_write_chapters(AVFormatContext *s) return ret; editionentry = start_ebml_master(dyn_cp, MATROSKA_ID_EDITIONENTRY, 0); - if (mkv->mode != MODE_WEBM) { + if (!IS_WEBM(mkv)) { put_ebml_uint(dyn_cp, MATROSKA_ID_EDITIONFLAGDEFAULT, 1); /* If mkv_write_tags() has already been called, then any tags * corresponding to chapters will be put into a new Tags element. */ @@ -1808,7 +1869,7 @@ static int mkv_write_header(AVFormatContext *s) int ret, i, version = 2; int64_t creation_time; - if (mkv->mode != MODE_WEBM || + if (!IS_WEBM(mkv) || av_dict_get(s->metadata, "stereo_mode", NULL, 0) || av_dict_get(s->metadata, "alpha_mode", NULL, 0)) version = 4; @@ -1853,7 +1914,7 @@ static int mkv_write_header(AVFormatContext *s) else put_ebml_string(pb, MATROSKA_ID_WRITINGAPP, LIBAVFORMAT_IDENT); - if (mkv->mode != MODE_WEBM) + if (!IS_WEBM(mkv)) put_ebml_binary(pb, MATROSKA_ID_SEGMENTUID, mkv->segment_uid, 16); } else { const char *ident = "Lavf"; @@ -1901,7 +1962,7 @@ static int mkv_write_header(AVFormatContext *s) if (ret < 0) return ret; - if (mkv->mode != MODE_WEBM) { + if (!IS_WEBM(mkv)) { ret = mkv_write_attachments(s); if (ret < 0) return ret; @@ -1925,12 +1986,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; } @@ -1963,6 +2026,7 @@ static int mkv_blockgroup_size(int pkt_size, int track_num_size) return size; } +#if CONFIG_MATROSKA_MUXER static int mkv_strip_wavpack(const uint8_t *src, uint8_t **pdst, int *size) { uint8_t *dst; @@ -2015,6 +2079,7 @@ fail: av_freep(&dst); return ret; } +#endif static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, uint32_t blockid, const AVPacket *pkt, int keyframe) @@ -2042,6 +2107,7 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, pkt->size, pkt->pts, pkt->dts, pkt->duration, avio_tell(pb), 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); @@ -2049,11 +2115,13 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, (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_AV1) { - err = ff_av1_filter_obus_buf(pkt->data, &data, &size, &offset); } 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) { @@ -2062,7 +2130,8 @@ static int mkv_write_block(AVFormatContext *s, AVIOContext *pb, return err; } - if (par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { + if (CONFIG_MATROSKA_MUXER && + par->codec_id == AV_CODEC_ID_PRORES && size >= 8) { /* Matroska specification requires to remove the first QuickTime atom */ size -= 8; @@ -2214,6 +2283,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) &side_data_size); switch (par->codec_id) { +#if CONFIG_MATROSKA_MUXER case AV_CODEC_ID_AAC: if (side_data_size && mkv->track.bc) { int filler, output_sample_rate = 0; @@ -2255,6 +2325,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) par->extradata = old_extradata; } break; +#endif // FIXME: Remove the following once libaom starts propagating extradata during init() // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2012 case AV_CODEC_ID_AV1: @@ -2508,25 +2579,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); + 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", @@ -2534,6 +2611,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; @@ -2556,7 +2642,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); } @@ -2674,7 +2760,8 @@ static int mkv_init(struct AVFormatContext *s) si->avoid_negative_ts_use_pts = 1; } - if (!strcmp(s->oformat->name, "webm")) { + if (!CONFIG_MATROSKA_MUXER || + (CONFIG_WEBM_MUXER && !strcmp(s->oformat->name, "webm"))) { mkv->mode = MODE_WEBM; mkv->write_crc = 0; } else @@ -2708,7 +2795,7 @@ static int mkv_init(struct AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 1000); if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) { - if (mkv->mode == MODE_WEBM) { + if (IS_WEBM(mkv)) { av_log(s, AV_LOG_WARNING, "Stream %d will be ignored " "as WebM doesn't support attachments.\n", i); } else if (!get_mimetype(st)) { @@ -2731,12 +2818,12 @@ static int mkv_init(struct AVFormatContext *s) return 0; } -static int mkv_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mkv_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; - if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { + if (CONFIG_MATROSKA_MUXER && st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); } else if (st->codecpar->codec_id == AV_CODEC_ID_VP9) { @@ -2780,6 +2867,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/md5proto.c b/libavformat/md5proto.c index 0e04b90aac..14cefe719c 100644 --- a/libavformat/md5proto.c +++ b/libavformat/md5proto.c @@ -25,6 +25,7 @@ #include "libavutil/error.h" #include "avformat.h" #include "avio.h" +#include "internal.h" #include "url.h" struct MD5Context { @@ -57,14 +58,13 @@ static int md5_close(URLContext *h) { struct MD5Context *c = h->priv_data; const char *filename = h->filename; - uint8_t md5[16], buf[64]; + uint8_t md5[16], buf[2 * sizeof(md5) + 1]; URLContext *out; - int i, err = 0; + int err = 0; av_md5_final(c->md5, md5); - for (i = 0; i < sizeof(md5); i++) - snprintf(buf + i*2, 3, "%02x", md5[i]); - buf[i*2] = '\n'; + ff_data_to_hex(buf, md5, sizeof(md5), 1); + buf[2 * sizeof(md5)] = '\n'; av_strstart(filename, "md5:", &filename); @@ -74,10 +74,10 @@ static int md5_close(URLContext *h) h->protocol_whitelist, h->protocol_blacklist, h); if (err) return err; - err = ffurl_write(out, buf, i*2+1); + err = ffurl_write(out, buf, sizeof(buf)); ffurl_close(out); } else { - if (fwrite(buf, 1, i*2+1, stdout) < i*2+1) + if (fwrite(buf, 1, sizeof(buf), stdout) < sizeof(buf)) err = AVERROR(errno); } diff --git a/libavformat/moflex.c b/libavformat/moflex.c index 234b0fb06e..1d342417f7 100644 --- a/libavformat/moflex.c +++ b/libavformat/moflex.c @@ -172,7 +172,7 @@ static int moflex_read_sync(AVFormatContext *s) unsigned type, ssize, codec_id = 0; unsigned codec_type, width = 0, height = 0, sample_rate = 0, channels = 0; int stream_index = -1; - AVRational fps; + AVRational tb = av_make_q(0, 1); read_var_byte(s, &type); read_var_byte(s, &ssize); @@ -195,6 +195,7 @@ static int moflex_read_sync(AVFormatContext *s) return AVERROR_PATCHWELCOME; } sample_rate = avio_rb24(pb) + 1; + tb = av_make_q(1, sample_rate); channels = avio_r8(pb) + 1; break; case 1: @@ -208,8 +209,8 @@ static int moflex_read_sync(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Unsupported video codec: %d\n", codec_id); return AVERROR_PATCHWELCOME; } - fps.num = avio_rb16(pb); - fps.den = avio_rb16(pb); + tb.den = avio_rb16(pb); + tb.num = avio_rb16(pb); width = avio_rb16(pb); height = avio_rb16(pb); avio_skip(pb, type == 3 ? 3 : 2); @@ -237,10 +238,8 @@ static int moflex_read_sync(AVFormatContext *s) if (!st->priv_data) return AVERROR(ENOMEM); - if (sample_rate) - avpriv_set_pts_info(st, 63, 1, sample_rate); - else - avpriv_set_pts_info(st, 63, fps.den, fps.num); + if (tb.num) + avpriv_set_pts_info(st, 63, tb.num, tb.den); } } @@ -383,4 +382,5 @@ const AVInputFormat ff_moflex_demuxer = { .read_close = moflex_read_close, .extensions = "moflex", .flags = AVFMT_GENERIC_INDEX, + .flags_internal = FF_FMT_INIT_CLEANUP, }; diff --git a/libavformat/mov.c b/libavformat/mov.c index 57c67e3aac..e401cd39b5 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -55,6 +55,7 @@ #include "avformat.h" #include "internal.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "isom.h" #include "libavcodec/get_bits.h" @@ -77,7 +78,7 @@ typedef struct MOVParseTableEntry { static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom); static int mov_read_mfra(MOVContext *c, AVIOContext *f); -static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, +static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration); static int mov_metadata_track_or_disc_number(MOVContext *c, AVIOContext *pb, @@ -610,11 +611,13 @@ static int mov_read_dref(MOVContext *c, AVIOContext *pb, MOVAtom atom) for (i = 0; i < entries; i++) { MOVDref *dref = &sc->drefs[i]; uint32_t size = avio_rb32(pb); - int64_t next = avio_tell(pb) + size - 4; + int64_t next = avio_tell(pb); - if (size < 12) + if (size < 12 || next < 0 || next > INT64_MAX - size) return AVERROR_INVALIDDATA; + next += size - 4; + dref->type = avio_rl32(pb); avio_rb32(pb); // version + flags @@ -810,7 +813,7 @@ static int mov_read_dac3(MOVContext *c, AVIOContext *pb, MOVAtom atom) 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 = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = ff_ac3_channel_layout_tab[acmod]; if (lfeon) st->codecpar->channel_layout |= AV_CH_LOW_FREQUENCY; *ast = bsmod; @@ -843,7 +846,7 @@ 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 = avpriv_ac3_channel_layout_tab[acmod]; + st->codecpar->channel_layout = 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); @@ -979,6 +982,7 @@ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom) uint8_t output[64]; uint8_t file_checksum[20]; uint8_t calculated_checksum[20]; + char checksum_string[2 * sizeof(file_checksum) + 1]; struct AVSHA *sha; int i; int ret = 0; @@ -1003,10 +1007,9 @@ static int mov_read_adrm(MOVContext *c, AVIOContext *pb, MOVAtom atom) avio_read(pb, output, 4); // go to offset 4, absolute position 0x28d avio_read(pb, file_checksum, 20); - av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == "); // required by external tools - for (i = 0; i < 20; i++) - av_log(c->fc, AV_LOG_INFO, "%02x", file_checksum[i]); - av_log(c->fc, AV_LOG_INFO, "\n"); + // required by external tools + ff_data_to_hex(checksum_string, file_checksum, sizeof(file_checksum), 1); + av_log(c->fc, AV_LOG_INFO, "[aax] file checksum == %s\n", checksum_string); /* verify activation data */ if (!activation_bytes) { @@ -1930,6 +1933,8 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) // wrap a whole fiel atom inside of a glbl atom. unsigned size = avio_rb32(pb); unsigned type = avio_rl32(pb); + if (avio_feof(pb)) + return AVERROR_INVALIDDATA; avio_seek(pb, -8, SEEK_CUR); if (type == MKTAG('f','i','e','l') && size == atom.size) return mov_read_default(c, pb, atom); @@ -2538,6 +2543,10 @@ 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); + return AVERROR_INVALIDDATA; + } } else if (st->codecpar->codec_type==AVMEDIA_TYPE_SUBTITLE){ mov_parse_stsd_subtitle(c, pb, st, sc, size - (avio_tell(pb) - start_pos)); @@ -2917,6 +2926,8 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) unsigned int i, entries, alloc_size = 0; int64_t duration = 0; int64_t total_sample_count = 0; + int64_t current_dts = 0; + int64_t corrected_dts = 0; if (c->fc->nb_streams < 1) return 0; @@ -2938,7 +2949,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR(ENOMEM); for (i = 0; i < entries && !pb->eof_reached; i++) { - int sample_duration; + unsigned int sample_duration; unsigned int sample_count; unsigned int min_entries = FFMIN(FFMAX(i + 1, 1024 * 1024), entries); MOVStts *stts_data = av_fast_realloc(sc->stts_data, &alloc_size, @@ -2957,11 +2968,34 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->stts_data[i].count= sample_count; sc->stts_data[i].duration= sample_duration; - av_log(c->fc, AV_LOG_TRACE, "sample_count=%d, sample_duration=%d\n", + av_log(c->fc, AV_LOG_TRACE, "sample_count=%u, sample_duration=%u\n", sample_count, sample_duration); - duration+=(int64_t)sample_duration*(uint64_t)sample_count; - total_sample_count+=sample_count; + /* STTS sample offsets are uint32 but some files store it as int32 + * with negative values used to correct DTS delays. + There may be abnormally large values as well. */ + if (sample_duration > c->max_stts_delta) { + // assume high delta is a correction if negative when cast as int32 + int32_t delta_magnitude = (int32_t)sample_duration; + av_log(c->fc, AV_LOG_WARNING, "Too large sample offset %u in stts entry %u with count %u in st:%d. Clipping to 1.\n", + sample_duration, i, sample_count, st->index); + sc->stts_data[i].duration = 1; + corrected_dts += (delta_magnitude < 0 ? (int64_t)delta_magnitude : 1) * sample_count; + } else { + corrected_dts += sample_duration * sample_count; + } + + current_dts += sc->stts_data[i].duration * sample_count; + + if (current_dts > corrected_dts) { + int64_t drift = (current_dts - corrected_dts)/FFMAX(sample_count, 1); + uint32_t correction = (sc->stts_data[i].duration > drift) ? drift : sc->stts_data[i].duration - 1; + current_dts -= correction * sample_count; + sc->stts_data[i].duration -= correction; + } + + duration+=(int64_t)sc->stts_data[i].duration*(uint64_t)sc->stts_data[i].count; + total_sample_count+=sc->stts_data[i].count; } sc->stts_count = i; @@ -3191,7 +3225,7 @@ static int get_edit_list_entry(MOVContext *mov, static int find_prev_closest_index(AVStream *st, AVIndexEntry *e_old, int nb_old, - MOVStts* ctts_data, + MOVCtts* ctts_data, int64_t ctts_count, int64_t timestamp_pts, int flag, @@ -3342,17 +3376,17 @@ static void fix_index_entry_timestamps(AVStream* st, int end_index, int64_t end_ * Append a new ctts entry to ctts_data. * Returns the new ctts_count if successful, else returns -1. */ -static int64_t add_ctts_entry(MOVStts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, +static int64_t add_ctts_entry(MOVCtts** ctts_data, unsigned int* ctts_count, unsigned int* allocated_size, int count, int duration) { - MOVStts *ctts_buf_new; - const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVStts); + MOVCtts *ctts_buf_new; + const size_t min_size_needed = (*ctts_count + 1) * sizeof(MOVCtts); const size_t requested_size = min_size_needed > *allocated_size ? FFMAX(min_size_needed, 2 * (*allocated_size)) : min_size_needed; - if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVStts) - 1) + if ((unsigned)(*ctts_count) >= UINT_MAX / sizeof(MOVCtts) - 1) return -1; ctts_buf_new = av_fast_realloc(*ctts_data, allocated_size, requested_size); @@ -3486,7 +3520,7 @@ static void mov_fix_index(MOVContext *mov, AVStream *st) int nb_old = sti->nb_index_entries; const AVIndexEntry *e_old_end = e_old + nb_old; const AVIndexEntry *current = NULL; - MOVStts *ctts_data_old = msc->ctts_data; + MOVCtts *ctts_data_old = msc->ctts_data; int64_t ctts_index_old = 0; int64_t ctts_sample_old = 0; int64_t ctts_count_old = msc->ctts_count; @@ -3793,7 +3827,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int stps_index = 0; unsigned int i, j; uint64_t stream_size = 0; - MOVStts *ctts_data_old = sc->ctts_data; + MOVCtts *ctts_data_old = sc->ctts_data; unsigned int ctts_count_old = sc->ctts_count; if (sc->elst_count) { @@ -3848,13 +3882,10 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int distance = 0; unsigned int rap_group_index = 0; unsigned int rap_group_sample = 0; - int64_t last_dts = 0; - int64_t dts_correction = 0; int rap_group_present = sc->rap_group_count && sc->rap_group; int key_off = (sc->keyframe_count && sc->keyframes[0] > 0) || (sc->stps_count && sc->stps_data[0] > 0); current_dts -= sc->dts_shift; - last_dts = current_dts; if (!sc->sample_count || sti->nb_index_entries) return; @@ -3965,26 +3996,8 @@ static void mov_build_index(MOVContext *mov, AVStream *st) current_offset += sample_size; stream_size += sample_size; - /* A negative sample duration is invalid based on the spec, - * but some samples need it to correct the DTS. */ - if (sc->stts_data[stts_index].duration < 0) { - av_log(mov->fc, AV_LOG_WARNING, - "Invalid SampleDelta %d in STTS, at %d st:%d\n", - sc->stts_data[stts_index].duration, stts_index, - st->index); - dts_correction += sc->stts_data[stts_index].duration - 1; - sc->stts_data[stts_index].duration = 1; - } current_dts += sc->stts_data[stts_index].duration; - if (!dts_correction || current_dts + dts_correction > last_dts) { - current_dts += dts_correction; - dts_correction = 0; - } else { - /* Avoid creating non-monotonous DTS */ - dts_correction += current_dts - last_dts - 1; - current_dts = last_dts + 1; - } - last_dts = current_dts; + distance++; stts_sample++; current_sample++; @@ -4754,7 +4767,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVStream *st = NULL; FFStream *sti = NULL; MOVStreamContext *sc; - MOVStts *ctts_data; + MOVCtts *ctts_data; uint64_t offset; int64_t dts, pts = AV_NOPTS_VALUE; int data_offset = 0; @@ -4828,20 +4841,34 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) dts = frag_stream_info->first_tfra_pts; av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64 ", using it for dts\n", pts); - } else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE && !c->use_tfdt) { - // FIXME: sidx earliest_presentation_time is *PTS*, s.b. - // pts = frag_stream_info->sidx_pts; - dts = frag_stream_info->sidx_pts - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 - ", using it for pts\n", pts); - } else if (frag_stream_info->tfdt_dts != AV_NOPTS_VALUE) { - dts = frag_stream_info->tfdt_dts - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 - ", using it for dts\n", dts); } else { - dts = sc->track_end - sc->time_offset; - av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 - ", using it for dts\n", dts); + int has_tfdt = frag_stream_info->tfdt_dts != AV_NOPTS_VALUE; + int has_sidx = frag_stream_info->sidx_pts != AV_NOPTS_VALUE; + int fallback_tfdt = !c->use_tfdt && !has_sidx && has_tfdt; + int fallback_sidx = c->use_tfdt && !has_tfdt && has_sidx; + + if (fallback_sidx) { + av_log(c->fc, AV_LOG_DEBUG, "use_tfdt set but no tfdt found, using sidx instead\n"); + } + if (fallback_tfdt) { + av_log(c->fc, AV_LOG_DEBUG, "use_tfdt not set but no sidx found, using tfdt instead\n"); + } + + if (has_tfdt && c->use_tfdt || fallback_tfdt) { + dts = frag_stream_info->tfdt_dts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found tfdt time %"PRId64 + ", using it for dts\n", dts); + } else if (has_sidx && !c->use_tfdt || fallback_sidx) { + // FIXME: sidx earliest_presentation_time is *PTS*, s.b. + // pts = frag_stream_info->sidx_pts; + dts = frag_stream_info->sidx_pts - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found sidx time %"PRId64 + ", using it for pts\n", pts); + } else { + dts = sc->track_end - sc->time_offset; + av_log(c->fc, AV_LOG_DEBUG, "found track end time %"PRId64 + ", using it for dts\n", dts); + } } } else { dts = sc->track_end - sc->time_offset; @@ -5387,6 +5414,9 @@ static int mov_read_smdm(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_WARNING, "Unsupported Mastering Display Metadata box version %d\n", version); return 0; } + if (sc->mastering) + return AVERROR_INVALIDDATA; + avio_skip(pb, 3); /* flags */ sc->mastering = av_mastering_display_metadata_alloc(); @@ -7033,58 +7063,21 @@ static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; - uint32_t buf; - AVDOVIDecoderConfigurationRecord *dovi; - size_t dovi_size; + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; int ret; + int64_t read_size = atom.size; if (c->fc->nb_streams < 1) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - if ((uint64_t)atom.size > (1<<30) || atom.size < 4) - return AVERROR_INVALIDDATA; + // At most 24 bytes + read_size = FFMIN(read_size, ISOM_DVCC_DVVC_SIZE); - dovi = av_dovi_alloc(&dovi_size); - if (!dovi) - return AVERROR(ENOMEM); - - dovi->dv_version_major = avio_r8(pb); - dovi->dv_version_minor = avio_r8(pb); - - buf = avio_rb16(pb); - dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits - dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits - dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit - dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit - dovi->bl_present_flag = buf & 0x01; // 1 bit - if (atom.size >= 24) { // 4 + 4 + 4 * 4 - buf = avio_r8(pb); - dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits - } else { - // 0 stands for None - // Dolby Vision V1.2.93 profiles and levels - dovi->dv_bl_signal_compatibility_id = 0; - } - - ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF, - (uint8_t *)dovi, dovi_size); - if (ret < 0) { - av_free(dovi); + if ((ret = ffio_read_size(pb, buf, read_size)) < 0) return ret; - } - av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id - ); - - return 0; + return ff_isom_parse_dvcc_dvvc(c->fc, st, buf, read_size); } static int mov_read_kind(MOVContext *c, AVIOContext *pb, MOVAtom atom) @@ -7273,6 +7266,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','l','l','i'), mov_read_clli }, { MKTAG('d','v','c','C'), mov_read_dvcc_dvvc }, { 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 }, { 0, NULL } }; @@ -7989,12 +7983,15 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; if (st->duration > 0) { - if (sc->data_size > INT64_MAX / sc->time_scale / 8) { - av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", + /* Akin to sc->data_size * 8 * sc->time_scale / st->duration but accounting for overflows. */ + st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, st->duration); + if (st->codecpar->bit_rate == INT64_MIN) { + av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); - return AVERROR_INVALIDDATA; + st->codecpar->bit_rate = 0; + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; } - st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / st->duration; } } } @@ -8004,13 +8001,15 @@ static int mov_read_header(AVFormatContext *s) AVStream *st = s->streams[i]; MOVStreamContext *sc = st->priv_data; if (sc->duration_for_fps > 0) { - if (sc->data_size > INT64_MAX / sc->time_scale / 8) { - av_log(s, AV_LOG_ERROR, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", + /* Akin to sc->data_size * 8 * sc->time_scale / sc->duration_for_fps but accounting for overflows. */ + st->codecpar->bit_rate = av_rescale(sc->data_size, ((int64_t) sc->time_scale) * 8, sc->duration_for_fps); + if (st->codecpar->bit_rate == INT64_MIN) { + av_log(s, AV_LOG_WARNING, "Overflow during bit rate calculation %"PRId64" * 8 * %d\n", sc->data_size, sc->time_scale); - return AVERROR_INVALIDDATA; + st->codecpar->bit_rate = 0; + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; } - st->codecpar->bit_rate = sc->data_size * 8 * sc->time_scale / - sc->duration_for_fps; } } } @@ -8527,7 +8526,7 @@ static const AVOption mov_options[] = { FLAGS, "use_mfra_for" }, {"pts", "pts", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_MFRA_PTS}, 0, 0, FLAGS, "use_mfra_for" }, - {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 0}, + {"use_tfdt", "use tfdt for fragment timestamps", OFFSET(use_tfdt), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, FLAGS}, { "export_all", "Export unrecognized metadata entries", OFFSET(export_all), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, .flags = FLAGS }, @@ -8546,6 +8545,7 @@ static const AVOption mov_options[] = { { "decryption_key", "The media decryption key (hex)", OFFSET(decryption_key), AV_OPT_TYPE_BINARY, .flags = AV_OPT_FLAG_DECODING_PARAM }, { "enable_drefs", "Enable external track support.", OFFSET(enable_drefs), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS }, + { "max_stts_delta", "treat offsets above this value as invalid", OFFSET(max_stts_delta), AV_OPT_TYPE_INT, {.i64 = UINT_MAX-48000*10 }, 0, UINT_MAX, .flags = AV_OPT_FLAG_DECODING_PARAM }, { NULL }, }; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index d43a086f4b..4c868919ae 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -27,6 +27,7 @@ #include "movenc.h" #include "avformat.h" #include "avio_internal.h" +#include "dovi_isom.h" #include "riff.h" #include "avio.h" #include "isom.h" @@ -1636,7 +1637,7 @@ static int mov_get_rawvideo_codec_tag(AVFormatContext *s, MOVTrack *track) } } - pix_fmt = avpriv_find_pix_fmt(avpriv_pix_fmt_bps_mov, + pix_fmt = avpriv_pix_fmt_find(PIX_FMT_LIST_MOV, track->par->bits_per_coded_sample); if (tag == MKTAG('r','a','w',' ') && track->par->format != pix_fmt && @@ -1716,7 +1717,7 @@ static unsigned int validate_codec_tag(const AVCodecTag *const *tags, for (i = 0; tags && tags[i]; i++) { const AVCodecTag *codec_tags = tags[i]; while (codec_tags->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(codec_tags->tag) == avpriv_toupper4(tag) && + if (ff_toupper4(codec_tags->tag) == ff_toupper4(tag) && codec_tags->id == codec_id) return codec_tags->tag; codec_tags++; @@ -1911,28 +1912,19 @@ static int mov_write_sv3d_tag(AVFormatContext *s, AVIOContext *pb, AVSphericalMa static int mov_write_dvcc_dvvc_tag(AVFormatContext *s, AVIOContext *pb, AVDOVIDecoderConfigurationRecord *dovi) { + uint8_t buf[ISOM_DVCC_DVVC_SIZE]; + avio_wb32(pb, 32); /* size = 8 + 24 */ - if (dovi->dv_profile > 7) + if (dovi->dv_profile > 10) + ffio_wfourcc(pb, "dvwC"); + else if (dovi->dv_profile > 7) ffio_wfourcc(pb, "dvvC"); else ffio_wfourcc(pb, "dvcC"); - avio_w8(pb, dovi->dv_version_major); - avio_w8(pb, dovi->dv_version_minor); - avio_wb16(pb, (dovi->dv_profile << 9) | (dovi->dv_level << 3) | - (dovi->rpu_present_flag << 2) | (dovi->el_present_flag << 1) | - dovi->bl_present_flag); - avio_wb32(pb, (dovi->dv_bl_signal_compatibility_id << 28) | 0); - ffio_fill(pb, 0, 4 * 4); /* reserved */ - av_log(s, AV_LOG_DEBUG, "DOVI in %s box, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", - dovi->dv_profile > 7 ? "dvvC" : "dvcC", - dovi->dv_version_major, dovi->dv_version_minor, - dovi->dv_profile, dovi->dv_level, - dovi->rpu_present_flag, - dovi->el_present_flag, - dovi->bl_present_flag, - dovi->dv_bl_signal_compatibility_id); + ff_isom_put_dvcc_dvvc(s, buf, dovi); + avio_write(pb, buf, sizeof(buf)); + return 32; /* 8 + 24 */ } @@ -2432,7 +2424,7 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { MOVMuxContext *mov = s->priv_data; - MOVStts *ctts_entries; + MOVCtts *ctts_entries; uint32_t entries = 0; uint32_t atom_size; int i; @@ -2968,7 +2960,7 @@ static int64_t calc_pts_duration(MOVMuxContext *mov, MOVTrack *track) static int mov_write_mdhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { - int64_t duration = calc_pts_duration(mov, track); + int64_t duration = calc_samples_pts_duration(mov, track); int version = duration < INT32_MAX ? 0 : 1; if (track->mode == MODE_ISM) @@ -4288,7 +4280,6 @@ static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *va char buf[150]; len = FFMIN(sizeof(buf) / 2 - 1, len); ff_data_to_hex(buf, value, len, 0); - buf[2 * len] = '\0'; avio_printf(pb, "\n", name, buf); } @@ -5348,7 +5339,7 @@ static int mov_write_squashed_packet(AVFormatContext *s, MOVTrack *track) switch (track->st->codecpar->codec_id) { case AV_CODEC_ID_TTML: { - int had_packets = !!track->squashed_packet_queue; + int had_packets = !!track->squashed_packet_queue.head; if ((ret = ff_mov_generate_squashed_ttml_packet(s, track, squashed_packet)) < 0) { goto finish_squash; @@ -6196,9 +6187,10 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR(EINVAL); } + /* The following will reset pkt and is only allowed to be used + * because we return immediately. afterwards. */ if ((ret = avpriv_packet_list_put(&trk->squashed_packet_queue, - &trk->squashed_packet_queue_end, - pkt, av_packet_ref, 0)) < 0) { + pkt, NULL, 0)) < 0) { return ret; } @@ -6456,8 +6448,6 @@ static void mov_free(AVFormatContext *s) MOVMuxContext *mov = s->priv_data; int i; - av_packet_free(&mov->pkt); - if (!mov->tracks) return; @@ -6466,29 +6456,28 @@ static void mov_free(AVFormatContext *s) } for (i = 0; i < mov->nb_streams; i++) { - if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) - ff_mov_close_hinting(&mov->tracks[i]); - else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) - av_freep(&mov->tracks[i].par); - av_freep(&mov->tracks[i].cluster); - av_freep(&mov->tracks[i].frag_info); - av_packet_free(&mov->tracks[i].cover_image); + MOVTrack *const track = &mov->tracks[i]; - if (mov->tracks[i].eac3_priv) { - struct eac3_info *info = mov->tracks[i].eac3_priv; + if (track->tag == MKTAG('r','t','p',' ')) + ff_mov_close_hinting(track); + else if (track->tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) + av_freep(&track->par); + av_freep(&track->cluster); + av_freep(&track->frag_info); + av_packet_free(&track->cover_image); + + if (track->eac3_priv) { + struct eac3_info *info = track->eac3_priv; av_packet_free(&info->pkt); - av_freep(&mov->tracks[i].eac3_priv); + av_freep(&track->eac3_priv); } - if (mov->tracks[i].vos_len) - av_freep(&mov->tracks[i].vos_data); + if (track->vos_len) + av_freep(&track->vos_data); - ff_mov_cenc_free(&mov->tracks[i].cenc); - ffio_free_dyn_buf(&mov->tracks[i].mdat_buf); + ff_mov_cenc_free(&track->cenc); + ffio_free_dyn_buf(&track->mdat_buf); - if (mov->tracks[i].squashed_packet_queue) { - avpriv_packet_list_free(&(mov->tracks[i].squashed_packet_queue), - &(mov->tracks[i].squashed_packet_queue_end)); - } + avpriv_packet_list_free(&track->squashed_packet_queue); } av_freep(&mov->tracks); @@ -6567,6 +6556,7 @@ static int mov_init(AVFormatContext *s) int i, ret; mov->fc = s; + mov->pkt = ffformatcontext(s)->pkt; /* Default mode == MP4 */ mov->mode = MODE_MP4; @@ -6712,10 +6702,6 @@ static int mov_init(AVFormatContext *s) mov->nb_streams += mov->nb_meta_tmcd; } - mov->pkt = av_packet_alloc(); - if (!mov->pkt) - return AVERROR(ENOMEM); - // Reserve an extra stream for chapters for the case where chapters // are written in the trailer mov->tracks = av_calloc(mov->nb_streams + 1, sizeof(*mov->tracks)); @@ -7154,13 +7140,8 @@ static int compute_sidx_size(AVFormatContext *s) static int shift_data(AVFormatContext *s) { - int ret = 0, moov_size; + int moov_size; MOVMuxContext *mov = s->priv_data; - int64_t pos, pos_end; - uint8_t *buf, *read_buf[2]; - int read_buf_id = 0; - int read_size[2]; - AVIOContext *read_pb; if (mov->flags & FF_MOV_FLAG_FRAGMENT) moov_size = compute_sidx_size(s); @@ -7169,53 +7150,7 @@ static int shift_data(AVFormatContext *s) if (moov_size < 0) return moov_size; - buf = av_malloc(moov_size * 2); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = buf + moov_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 " - "the second pass (faststart)\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, mov->reserved_header_pos + moov_size, SEEK_SET); - - /* start reading at where the new moov will be placed */ - avio_seek(read_pb, mov->reserved_header_pos, 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], moov_size); \ - read_buf_id ^= 1; \ -} while (0) - - /* shift data by chunk of at most moov_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); - ff_format_io_close(s, &read_pb); - -end: - av_free(buf); - return ret; + return ff_format_shift_data(s, mov->reserved_header_pos, moov_size); } static int mov_write_trailer(AVFormatContext *s) @@ -7341,10 +7276,10 @@ static int mov_write_trailer(AVFormatContext *s) return res; } -static int mov_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mov_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 40077b1afe..2ac84ed070 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -167,7 +167,7 @@ typedef struct MOVTrack { unsigned int squash_fragment_samples_to_one; //< flag to note formats where all samples for a fragment are to be squashed - PacketList *squashed_packet_queue, *squashed_packet_queue_end; + PacketList squashed_packet_queue; } MOVTrack; typedef enum { diff --git a/libavformat/movenc_ttml.c b/libavformat/movenc_ttml.c index 472572b45a..6deae49657 100644 --- a/libavformat/movenc_ttml.c +++ b/libavformat/movenc_ttml.c @@ -70,9 +70,7 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, return ret; } - while (!avpriv_packet_list_get(&track->squashed_packet_queue, - &track->squashed_packet_queue_end, - pkt)) { + while (!avpriv_packet_list_get(&track->squashed_packet_queue, pkt)) { end_ts = FFMAX(end_ts, pkt->pts + pkt->duration); // in case of the 'dfxp' muxing mode, each written document is offset @@ -121,7 +119,7 @@ int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, goto cleanup; } - if (!track->squashed_packet_queue) { + if (!track->squashed_packet_queue.head) { // empty queue, write minimal empty document with zero duration avio_write(ttml_ctx->pb, empty_ttml_document, sizeof(empty_ttml_document) - 1); diff --git a/libavformat/mp3enc.c b/libavformat/mp3enc.c index e4b2a65b07..3ff19da274 100644 --- a/libavformat/mp3enc.c +++ b/libavformat/mp3enc.c @@ -132,7 +132,7 @@ typedef struct MP3Context { int pics_to_write; /* audio packets are queued here until we get all the attached pictures */ - PacketList *queue, *queue_end; + PacketList queue; } MP3Context; static const uint8_t xing_offtbl[2][2] = {{32, 17}, {17, 9}}; @@ -159,8 +159,8 @@ static int mp3_write_xing(AVFormatContext *s) if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) || !mp3->write_xing) return 0; - for (i = 0; i < FF_ARRAY_ELEMS(avpriv_mpa_freq_tab); i++) { - const uint16_t base_freq = avpriv_mpa_freq_tab[i]; + for (i = 0; i < FF_ARRAY_ELEMS(ff_mpa_freq_tab); i++) { + const uint16_t base_freq = ff_mpa_freq_tab[i]; if (par->sample_rate == base_freq) ver = 0x3; // MPEG 1 else if (par->sample_rate == base_freq / 2) ver = 0x2; // MPEG 2 @@ -170,7 +170,7 @@ static int mp3_write_xing(AVFormatContext *s) srate_idx = i; break; } - if (i == FF_ARRAY_ELEMS(avpriv_mpa_freq_tab)) { + if (i == FF_ARRAY_ELEMS(ff_mpa_freq_tab)) { av_log(s, AV_LOG_WARNING, "Unsupported sample rate, not writing Xing header.\n"); return -1; } @@ -190,7 +190,7 @@ static int mp3_write_xing(AVFormatContext *s) header |= channels << 6; for (bitrate_idx = 1; bitrate_idx < 15; bitrate_idx++) { - int bit_rate = 1000 * avpriv_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; + int bit_rate = 1000 * ff_mpa_bitrate_tab[ver != 3][3 - 1][bitrate_idx]; int error = FFABS(bit_rate - par->bit_rate); if (error < best_bitrate_error) { @@ -387,8 +387,8 @@ static int mp3_queue_flush(AVFormatContext *s) ff_id3v2_finish(&mp3->id3, s->pb, s->metadata_header_padding); mp3_write_xing(s); - while (mp3->queue) { - avpriv_packet_list_get(&mp3->queue, &mp3->queue_end, pkt); + while (mp3->queue.head) { + avpriv_packet_list_get(&mp3->queue, pkt); if (write && (ret = mp3_write_audio_packet(s, pkt)) < 0) write = 0; av_packet_unref(pkt); @@ -524,7 +524,7 @@ static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt) if (pkt->stream_index == mp3->audio_stream_idx) { if (mp3->pics_to_write) { /* buffer audio packets until we get all the pictures */ - int ret = avpriv_packet_list_put(&mp3->queue, &mp3->queue_end, pkt, av_packet_ref, 0); + int ret = avpriv_packet_list_put(&mp3->queue, pkt, NULL, 0); if (ret < 0) { av_log(s, AV_LOG_WARNING, "Not enough memory to buffer audio. Skipping picture streams\n"); @@ -632,7 +632,7 @@ static void mp3_deinit(struct AVFormatContext *s) { MP3Context *mp3 = s->priv_data; - avpriv_packet_list_free(&mp3->queue, &mp3->queue_end); + avpriv_packet_list_free(&mp3->queue); av_freep(&mp3->xing_frame); } diff --git a/libavformat/mpeg4audio_sample_rates.c b/libavformat/mpeg4audio_sample_rates.c new file mode 100644 index 0000000000..212385f348 --- /dev/null +++ b/libavformat/mpeg4audio_sample_rates.c @@ -0,0 +1,23 @@ +/* + * MPEG-4 Audio sample rates + * Copyright (c) 2008 Baptiste Coudurier + * Copyright (c) 2009 Alex Converse + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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/mpeg4audio_sample_rates.h" diff --git a/libavformat/mpegaudiotabs.c b/libavformat/mpegaudiotabs.c new file mode 100644 index 0000000000..41ac76e21b --- /dev/null +++ b/libavformat/mpegaudiotabs.c @@ -0,0 +1,22 @@ +/* + * MPEG Audio common tables + * copyright (c) 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 "libavcodec/mpegaudiotabs.h" diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 44d9298b12..2479cb6f7d 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -807,6 +807,7 @@ static const StreamType ISO_types[] = { { 0x42, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_CAVS }, { 0xd1, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_DIRAC }, { 0xd2, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS2 }, + { 0xd4, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_AVS3 }, { 0xea, AVMEDIA_TYPE_VIDEO, AV_CODEC_ID_VC1 }, { 0 }, }; @@ -937,10 +938,9 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes, // audio track - add a second stream for this AVStream *sub_st; // priv_data cannot be shared between streams - PESContext *sub_pes = av_malloc(sizeof(*sub_pes)); + PESContext *sub_pes = av_memdup(pes, sizeof(*sub_pes)); if (!sub_pes) return AVERROR(ENOMEM); - memcpy(sub_pes, pes, sizeof(*sub_pes)); sub_st = avformat_new_stream(pes->stream, NULL); if (!sub_st) { @@ -2178,6 +2178,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type AVDOVIDecoderConfigurationRecord *dovi; size_t dovi_size; int ret; + int dependency_pid; + if (desc_end - *pp < 4) // (8 + 8 + 7 + 6 + 1 + 1 + 1) / 8 return AVERROR_INVALIDDATA; @@ -2193,7 +2195,11 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit dovi->bl_present_flag = buf & 0x01; // 1 bit - if (desc_end - *pp >= 20) { // 4 + 4 * 4 + if (!dovi->bl_present_flag && desc_end - *pp >= 2) { + buf = get16(pp, desc_end); + dependency_pid = buf >> 3; // 13 bits + } + if (desc_end - *pp >= 1) { // 8 bits buf = get8(pp, desc_end); dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits } else { @@ -2210,12 +2216,13 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } av_log(fc, AV_LOG_TRACE, "DOVI, version: %d.%d, profile: %d, level: %d, " - "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n", + "rpu flag: %d, el flag: %d, bl flag: %d, dependency_pid: %d, compatibility id: %d\n", dovi->dv_version_major, dovi->dv_version_minor, dovi->dv_profile, dovi->dv_level, dovi->rpu_present_flag, dovi->el_present_flag, dovi->bl_present_flag, + dependency_pid, dovi->dv_bl_signal_compatibility_id); } break; @@ -2230,11 +2237,10 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int p int stream_identifier, int pmt_stream_idx, struct Program *p) { AVFormatContext *s = ts->stream; - int i; AVStream *found = NULL; if (stream_identifier) { /* match based on "stream identifier descriptor" if present */ - for (i = 0; i < p->nb_streams; i++) { + for (int i = 0; i < p->nb_streams; i++) { if (p->streams[i].stream_identifier == stream_identifier) if (!found || pmt_stream_idx == i) /* fallback to idx based guess if multiple streams have the same identifier */ found = s->streams[p->streams[i].idx]; @@ -2247,7 +2253,7 @@ static AVStream *find_matching_stream(MpegTSContext *ts, int pid, unsigned int p av_log(ts->stream, AV_LOG_VERBOSE, "re-using existing %s stream %d (pid=0x%x) for new pid=0x%x\n", av_get_media_type_string(found->codecpar->codec_type), - i, found->id, pid); + found->index, found->id, pid); } return found; diff --git a/libavformat/mpegts.h b/libavformat/mpegts.h index 910d65af8c..a48f14e768 100644 --- a/libavformat/mpegts.h +++ b/libavformat/mpegts.h @@ -130,6 +130,7 @@ #define STREAM_TYPE_VIDEO_HEVC 0x24 #define STREAM_TYPE_VIDEO_CAVS 0x42 #define STREAM_TYPE_VIDEO_AVS2 0xd2 +#define STREAM_TYPE_VIDEO_AVS3 0xd4 #define STREAM_TYPE_VIDEO_VC1 0xea #define STREAM_TYPE_VIDEO_DIRAC 0xd1 diff --git a/libavformat/mpegtsenc.c b/libavformat/mpegtsenc.c index f3b7914175..92b4cc8087 100644 --- a/libavformat/mpegtsenc.c +++ b/libavformat/mpegtsenc.c @@ -369,6 +369,9 @@ static int get_dvb_stream_type(AVFormatContext *s, AVStream *st) case AV_CODEC_ID_AVS2: stream_type = STREAM_TYPE_VIDEO_AVS2; break; + case AV_CODEC_ID_AVS3: + stream_type = STREAM_TYPE_VIDEO_AVS3; + break; case AV_CODEC_ID_DIRAC: stream_type = STREAM_TYPE_VIDEO_DIRAC; break; @@ -786,6 +789,9 @@ static int mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) put_registration_descriptor(&q, MKTAG('V', 'C', '-', '1')); } else if (stream_type == STREAM_TYPE_VIDEO_HEVC && s->strict_std_compliance <= FF_COMPLIANCE_NORMAL) { put_registration_descriptor(&q, MKTAG('H', 'E', 'V', 'C')); + } else if (stream_type == STREAM_TYPE_VIDEO_CAVS || stream_type == STREAM_TYPE_VIDEO_AVS2 || + stream_type == STREAM_TYPE_VIDEO_AVS3) { + put_registration_descriptor(&q, MKTAG('A', 'V', 'S', 'V')); } break; case AVMEDIA_TYPE_DATA: @@ -1134,9 +1140,7 @@ static int mpegts_init(AVFormatContext *s) ts->nit.write_packet = section_write_packet; ts->nit.opaque = s; - ts->pkt = av_packet_alloc(); - if (!ts->pkt) - return AVERROR(ENOMEM); + ts->pkt = ffformatcontext(s)->pkt; /* assign pids to each stream */ for (i = 0; i < s->nb_streams; i++) { @@ -1558,7 +1562,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, q = get_ts_payload_start(buf); ts_st->discontinuity = 0; } - if (key && is_start && pts != AV_NOPTS_VALUE) { + if (key && is_start && pts != AV_NOPTS_VALUE && + !is_dvb_teletext /* adaptation+payload forbidden for teletext (ETSI EN 300 472 V1.3.1 4.1) */) { // set Random Access for key frames if (ts_st->pcr_period) write_pcr = 1; @@ -1846,12 +1851,12 @@ static int mpegts_write_packet_internal(AVFormatContext *s, AVPacket *pkt) if (side_data) stream_id = side_data[0]; - if (ts->copyts < 1) { - if (!ts->first_dts_checked && dts != AV_NOPTS_VALUE) { - ts->first_pcr += dts * 300; - ts->first_dts_checked = 1; - } + if (!ts->first_dts_checked && dts != AV_NOPTS_VALUE) { + ts->first_pcr += dts * 300; + ts->first_dts_checked = 1; + } + if (ts->copyts < 1) { if (pts != AV_NOPTS_VALUE) pts += delay; if (dts != AV_NOPTS_VALUE) @@ -2179,8 +2184,6 @@ static void mpegts_deinit(AVFormatContext *s) MpegTSService *service; int i; - av_packet_free(&ts->pkt); - for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; MpegTSWriteStream *ts_st = st->priv_data; @@ -2201,10 +2204,10 @@ static void mpegts_deinit(AVFormatContext *s) av_freep(&ts->services); } -static int mpegts_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int mpegts_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { int ret = 1; - AVStream *st = s->streams[pkt->stream_index]; if (st->codecpar->codec_id == AV_CODEC_ID_H264) { if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && diff --git a/libavformat/mux.c b/libavformat/mux.c index a6e1a08be0..c387f8ec6e 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -204,7 +204,7 @@ static int validate_codec_tag(AVFormatContext *s, AVStream *st) for (int n = 0; s->oformat->codec_tag[n]; n++) { avctag = s->oformat->codec_tag[n]; while (avctag->id != AV_CODEC_ID_NONE) { - if (avpriv_toupper4(avctag->tag) == avpriv_toupper4(st->codecpar->codec_tag)) { + if (ff_toupper4(avctag->tag) == ff_toupper4(st->codecpar->codec_tag)) { id = avctag->id; if (id == st->codecpar->codec_id) return 1; @@ -334,6 +334,11 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) si->nb_interleaved_streams++; } + si->interleave_packet = of->interleave_packet; + if (!si->interleave_packet) + si->interleave_packet = si->nb_interleaved_streams > 1 ? + ff_interleave_packet_per_dts : + ff_interleave_packet_passthrough; if (!s->priv_data && of->priv_data_size > 0) { s->priv_data = av_mallocz(of->priv_data_size); @@ -804,12 +809,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, { int ret; FFFormatContext *const si = ffformatcontext(s); - PacketList **next_point, *this_pktl; + PacketListEntry **next_point, *this_pktl; AVStream *st = s->streams[pkt->stream_index]; FFStream *const sti = ffstream(st); int chunked = s->max_chunk_size || s->max_chunk_duration; - this_pktl = av_malloc(sizeof(PacketList)); + this_pktl = av_malloc(sizeof(*this_pktl)); if (!this_pktl) { av_packet_unref(pkt); return AVERROR(ENOMEM); @@ -826,7 +831,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (sti->last_in_packet_buffer) { next_point = &(sti->last_in_packet_buffer->next); } else { - next_point = &si->packet_buffer; + next_point = &si->packet_buffer.head; } if (chunked) { @@ -850,7 +855,7 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (chunked && !(pkt->flags & CHUNK_START)) goto next_non_null; - if (compare(s, &si->packet_buffer_end->pkt, pkt)) { + if (compare(s, &si->packet_buffer.tail->pkt, pkt)) { while ( *next_point && ((chunked && !((*next_point)->pkt.flags&CHUNK_START)) || !compare(s, &(*next_point)->pkt, pkt))) @@ -858,12 +863,12 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, if (*next_point) goto next_non_null; } else { - next_point = &(si->packet_buffer_end->next); + next_point = &(si->packet_buffer.tail->next); } } av_assert1(!*next_point); - si->packet_buffer_end = this_pktl; + si->packet_buffer.tail = this_pktl; next_non_null: this_pktl->next = *next_point; @@ -934,11 +939,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, flush = 1; if (s->max_interleave_delta > 0 && - si->packet_buffer && + si->packet_buffer.head && !flush && si->nb_interleaved_streams == stream_count+noninterleaved_count ) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; int64_t delta_dts = INT64_MIN; int64_t top_dts = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -947,7 +952,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, for (unsigned i = 0; i < s->nb_streams; i++) { const AVStream *const st = s->streams[i]; const FFStream *const sti = cffstream(st); - const PacketList *last = sti->last_in_packet_buffer; + const PacketListEntry *const last = sti->last_in_packet_buffer; int64_t last_dts; if (!last) @@ -968,11 +973,11 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } } - if (si->packet_buffer && + if (si->packet_buffer.head && eof && (s->flags & AVFMT_FLAG_SHORTEST) && si->shortest_end == AV_NOPTS_VALUE) { - AVPacket *const top_pkt = &si->packet_buffer->pkt; + AVPacket *const top_pkt = &si->packet_buffer.head->pkt; si->shortest_end = av_rescale_q(top_pkt->dts, s->streams[top_pkt->stream_index]->time_base, @@ -980,8 +985,8 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (si->shortest_end != AV_NOPTS_VALUE) { - while (si->packet_buffer) { - PacketList *pktl = si->packet_buffer; + while (si->packet_buffer.head) { + PacketListEntry *pktl = si->packet_buffer.head; AVPacket *const top_pkt = &pktl->pkt; AVStream *const st = s->streams[top_pkt->stream_index]; FFStream *const sti = ffstream(st); @@ -991,9 +996,9 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, if (si->shortest_end + 1 >= top_dts) break; - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; + si->packet_buffer.head = pktl->next; + if (!si->packet_buffer.head) + si->packet_buffer.tail = NULL; if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; @@ -1005,19 +1010,13 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } if (stream_count && flush) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; AVStream *const st = s->streams[pktl->pkt.stream_index]; FFStream *const sti = ffstream(st); - *pkt = pktl->pkt; - - si->packet_buffer = pktl->next; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - if (sti->last_in_packet_buffer == pktl) sti->last_in_packet_buffer = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, pkt); return 1; } else { @@ -1025,6 +1024,12 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *pkt, } } +int ff_interleave_packet_passthrough(AVFormatContext *s, AVPacket *pkt, + int flush, int has_packet) +{ + return has_packet; +} + int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset) { AVStream *st; @@ -1044,7 +1049,7 @@ int ff_get_muxer_ts_offset(AVFormatContext *s, int stream_index, int64_t *offset const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) { FFFormatContext *const si = ffformatcontext(s); - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; while (pktl) { if (pktl->pkt.stream_index == stream) { return &pktl->pkt; @@ -1054,19 +1059,6 @@ const AVPacket *ff_interleaved_peek(AVFormatContext *s, int stream) return NULL; } -/** - * A wrapper around AVOutputFormat.interleave_packet. - * See its documentation for details. - */ -static int interleave_packet(AVFormatContext *s, AVPacket *pkt, - int flush, int has_packet) -{ - if (s->oformat->interleave_packet) { - return s->oformat->interleave_packet(s, pkt, flush, has_packet); - } else - return ff_interleave_packet_per_dts(s, pkt, flush, has_packet); -} - static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) { int ret; @@ -1076,7 +1068,7 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) if (s->oformat->check_bitstream) { if (!sti->bitstream_checked) { - if ((ret = s->oformat->check_bitstream(s, pkt)) < 0) + if ((ret = s->oformat->check_bitstream(s, &sti->pub, pkt)) < 0) return ret; else if (ret == 1) sti->bitstream_checked = 1; @@ -1089,8 +1081,9 @@ static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt) static int interleaved_write_packet(AVFormatContext *s, AVPacket *pkt, int flush, int has_packet) { + FFFormatContext *const si = ffformatcontext(s); for (;; ) { - int ret = interleave_packet(s, pkt, flush, has_packet); + int ret = si->interleave_packet(s, pkt, flush, has_packet); if (ret <= 0) return ret; diff --git a/libavformat/mvdec.c b/libavformat/mvdec.c index d58281c3a9..4f233aff5f 100644 --- a/libavformat/mvdec.c +++ b/libavformat/mvdec.c @@ -26,6 +26,7 @@ #include "libavutil/channel_layout.h" #include "libavutil/eval.h" +#include "libavutil/intfloat.h" #include "libavutil/intreadwrite.h" #include "libavutil/rational.h" @@ -44,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) @@ -299,21 +304,33 @@ static int mv_read_header(AVFormatContext *avctx) if (version == 2) { uint64_t timestamp; int v; - avio_skip(pb, 22); + uint32_t bytes_per_sample; + AVRational fps; + + 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); - avpriv_set_pts_info(vst, 64, 1, 15); + avpriv_set_pts_info(vst, 64, fps.den, fps.num); vst->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - vst->avg_frame_rate = av_inv_q(vst->time_base); - vst->nb_frames = avio_rb32(pb); + vst->avg_frame_rate = fps; + vst->duration = vst->nb_frames = avio_rb32(pb); v = avio_rb32(pb); switch (v) { case 1: @@ -332,25 +349,45 @@ 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); - if (set_channels(avctx, ast, avio_rb32(pb)) < 0) - return AVERROR_INVALIDDATA; + 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; + } + avpriv_set_pts_info(ast, 33, 1, ast->codecpar->sample_rate); - v = avio_rb32(pb); - if (v == AUDIO_FORMAT_SIGNED) { - ast->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; - } else { - avpriv_request_sample(avctx, "Audio compression (format %i)", v); - } + 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; + } + } else { + avpriv_request_sample(avctx, "Audio compression (format %i)", v); + } + + 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 */ - avio_skip(pb, 12); var_read_metadata(avctx, "title", 0x80); var_read_metadata(avctx, "comment", 0x100); avio_skip(pb, 0x80); @@ -363,9 +400,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->channels * (uint64_t)bytes_per_sample); + } av_add_index_entry(vst, pos + asize, i, vsize, 0, AVINDEX_KEYFRAME); - timestamp += asize / (ast->codecpar->channels * 2LL); } } else if (!version && avio_rb16(pb) == 3) { avio_skip(pb, 4); diff --git a/libavformat/mxf.h b/libavformat/mxf.h index fe9c52732c..d53a16df51 100644 --- a/libavformat/mxf.h +++ b/libavformat/mxf.h @@ -50,6 +50,9 @@ enum MXFMetadataSetType { TaggedValue, TapeDescriptor, AVCSubDescriptor, + AudioChannelLabelSubDescriptor, + SoundfieldGroupLabelSubDescriptor, + GroupOfSoundfieldGroupsLabelSubDescriptor, }; enum MXFFrameLayout { diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c index af9d33f796..b85c10bf19 100644 --- a/libavformat/mxfdec.c +++ b/libavformat/mxfdec.c @@ -51,11 +51,14 @@ #include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavcodec/bytestream.h" +#include "libavcodec/internal.h" +#include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "libavutil/parseutils.h" #include "libavutil/timecode.h" #include "libavutil/opt.h" #include "avformat.h" +#include "avlanguage.h" #include "internal.h" #include "mxf.h" @@ -177,6 +180,8 @@ typedef struct { int body_sid; MXFWrappingScheme wrapping; int edit_units_per_packet; /* how many edit units to read at a time (PCM, ClipWrapped) */ + int require_reordering; + int channel_ordering[FF_SANE_NB_CHANNELS]; } MXFTrack; typedef struct MXFDescriptor { @@ -205,6 +210,8 @@ typedef struct MXFDescriptor { unsigned int vert_subsampling; UID *file_descriptors_refs; int file_descriptors_count; + UID *sub_descriptors_refs; + int sub_descriptors_count; int linked_track_id; uint8_t *extradata; int extradata_size; @@ -217,6 +224,18 @@ typedef struct MXFDescriptor { size_t coll_size; } MXFDescriptor; +typedef struct MXFMCASubDescriptor { + MXFMetadataSet meta; + UID uid; + UID mca_link_id; + UID soundfield_group_link_id; + UID *group_of_soundfield_groups_link_id_refs; + int group_of_soundfield_groups_link_id_count; + UID mca_label_dictionary_id; + int mca_channel_id; + char *language; +} MXFMCASubDescriptor; + typedef struct MXFIndexTableSegment { MXFMetadataSet meta; int edit_unit_byte_count; @@ -311,6 +330,7 @@ static const uint8_t mxf_system_item_key_cp[] = { 0x06,0x0e,0x2b,0x static const uint8_t mxf_system_item_key_gc[] = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x03,0x01,0x14 }; static const uint8_t mxf_klv_key[] = { 0x06,0x0e,0x2b,0x34 }; static const uint8_t mxf_apple_coll_prefix[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01 }; + /* complete keys to match */ static const uint8_t mxf_crypto_source_container_ul[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x02,0x02,0x00,0x00,0x00 }; static const uint8_t mxf_encrypted_triplet_key[] = { 0x06,0x0e,0x2b,0x34,0x02,0x04,0x01,0x07,0x0d,0x01,0x03,0x01,0x02,0x7e,0x01,0x00 }; @@ -323,6 +343,17 @@ static const uint8_t mxf_indirect_value_utf16be[] = { 0x42,0x01,0x10,0x static const uint8_t mxf_apple_coll_max_cll[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x01 }; static const uint8_t mxf_apple_coll_max_fall[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x0e,0x20,0x04,0x01,0x05,0x03,0x01,0x02 }; +static const uint8_t mxf_mca_label_dictionary_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x01,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_symbol[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x02,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_tag_name[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x03,0x00,0x00,0x00 }; +static const uint8_t mxf_group_of_soundfield_groups_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x04,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x05,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_channel_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x04,0x0a,0x00,0x00,0x00,0x00 }; +static const uint8_t mxf_soundfield_group_link_id[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0e,0x01,0x03,0x07,0x01,0x06,0x00,0x00,0x00 }; +static const uint8_t mxf_mca_rfc5646_spoken_language[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x0d,0x03,0x01,0x01,0x02,0x03,0x15,0x00,0x00 }; + +static const uint8_t mxf_sub_descriptor[] = { 0x06,0x0e,0x2b,0x34,0x01,0x01,0x01,0x09,0x06,0x01,0x01,0x04,0x06,0x10,0x00,0x00 }; + static const uint8_t mxf_mastering_display_prefix[13] = { FF_MXF_MasteringDisplay_PREFIX }; static const uint8_t mxf_mastering_display_uls[4][16] = { FF_MXF_MasteringDisplayPrimaries, @@ -343,6 +374,13 @@ static void mxf_free_metadataset(MXFMetadataSet **ctx, int freectx) av_freep(&((MXFDescriptor *)*ctx)->mastering); av_freep(&((MXFDescriptor *)*ctx)->coll); av_freep(&((MXFDescriptor *)*ctx)->file_descriptors_refs); + av_freep(&((MXFDescriptor *)*ctx)->sub_descriptors_refs); + break; + case AudioChannelLabelSubDescriptor: + case SoundfieldGroupLabelSubDescriptor: + case GroupOfSoundfieldGroupsLabelSubDescriptor: + av_freep(&((MXFMCASubDescriptor *)*ctx)->language); + av_freep(&((MXFMCASubDescriptor *)*ctx)->group_of_soundfield_groups_link_id_refs); break; case Sequence: av_freep(&((MXFSequence *)*ctx)->structural_components_refs); @@ -906,6 +944,30 @@ static int mxf_read_strong_ref_array(AVIOContext *pb, UID **refs, int *count) return 0; } +static inline int mxf_read_us_ascii_string(AVIOContext *pb, int size, char** str) +{ + int ret; + size_t buf_size; + + if (size < 0 || size > INT_MAX - 1) + return AVERROR(EINVAL); + + buf_size = size + 1; + av_free(*str); + *str = av_malloc(buf_size); + if (!*str) + return AVERROR(ENOMEM); + + ret = avio_get_str(pb, size, *str, buf_size); + + if (ret < 0) { + av_freep(str); + return ret; + } + + return ret; +} + static inline int mxf_read_utf16_string(AVIOContext *pb, int size, char** str, int be) { int ret; @@ -1111,6 +1173,9 @@ static int mxf_read_index_entry_array(AVIOContext *pb, MXFIndexTableSegment *seg { int i, length; + if (segment->temporal_offset_entries) + return AVERROR_INVALIDDATA; + segment->nb_index_entries = avio_rb32(pb); length = avio_rb32(pb); @@ -1360,11 +1425,40 @@ static int mxf_read_generic_descriptor(void *arg, AVIOContext *pb, int tag, int descriptor->coll->MaxFALL = avio_rb16(pb); } } + + if (IS_KLV_KEY(uid, mxf_sub_descriptor)) + return mxf_read_strong_ref_array(pb, &descriptor->sub_descriptors_refs, &descriptor->sub_descriptors_count); + break; } return 0; } +static int mxf_read_mca_sub_descriptor(void *arg, AVIOContext *pb, int tag, int size, UID uid, int64_t klv_offset) +{ + MXFMCASubDescriptor *mca_sub_descriptor = arg; + + if (IS_KLV_KEY(uid, mxf_mca_label_dictionary_id)) + avio_read(pb, mca_sub_descriptor->mca_label_dictionary_id, 16); + + if (IS_KLV_KEY(uid, mxf_mca_link_id)) + avio_read(pb, mca_sub_descriptor->mca_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_soundfield_group_link_id)) + avio_read(pb, mca_sub_descriptor->soundfield_group_link_id, 16); + + if (IS_KLV_KEY(uid, mxf_group_of_soundfield_groups_link_id)) + return mxf_read_strong_ref_array(pb, &mca_sub_descriptor->group_of_soundfield_groups_link_id_refs, &mca_sub_descriptor->group_of_soundfield_groups_link_id_count); + + if (IS_KLV_KEY(uid, mxf_mca_channel_id)) + mca_sub_descriptor->mca_channel_id = avio_rb32(pb); + + if (IS_KLV_KEY(uid, mxf_mca_rfc5646_spoken_language)) + return mxf_read_us_ascii_string(pb, size, &mca_sub_descriptor->language); + + return 0; +} + static int mxf_read_indirect_value(void *arg, AVIOContext *pb, int size) { MXFTaggedValue *tagged_value = arg; @@ -1494,6 +1588,52 @@ static const MXFCodecUL mxf_data_essence_container_uls[] = { { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, }; +typedef struct MXFChannelOrderingUL { + UID uid; + uint64_t layout_mask; + enum AVAudioServiceType service_type; +} MXFChannelOrderingUL; + +static const MXFChannelOrderingUL mxf_channel_ordering[] = { + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x02,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x03,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x04,0x00,0x00,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Low Frequency Effects + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x05,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x06,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x07,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x08,0x00,0x00,0x00,0x00 }, AV_CH_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x09,0x00,0x00,0x00,0x00 }, AV_CH_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0a,0x00,0x00,0x00,0x00 }, AV_CH_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0b,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_LEFT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0c,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_RIGHT_OF_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Center + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0d,0x00,0x00,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0e,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_VISUALLY_IMPAIRED }, // Hearing impaired audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x0f,0x00,0x00,0x00,0x00 }, AV_CH_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_HEARING_IMPAIRED }, // Visually impaired narrative audio channel + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x03,0x00,0x00,0x00 }, AV_CH_STEREO_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Total + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x20,0x04,0x00,0x00,0x00 }, AV_CH_STEREO_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Total + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x01,0x00,0x00 }, AV_CH_TOP_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x02,0x00,0x00 }, AV_CH_TOP_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x03,0x00,0x00 }, AV_CH_TOP_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x04,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x05,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x06,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x07,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Side Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x08,0x00,0x00 }, AV_CH_TOP_BACK_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x09,0x00,0x00 }, AV_CH_TOP_BACK_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Rear Surround Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0a,0x00,0x00 }, AV_CH_TOP_SIDE_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0b,0x00,0x00 }, AV_CH_TOP_SIDE_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0c,0x00,0x00 }, AV_CH_TOP_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Top Surround + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0d,0x00,0x00 }, AV_CH_LOW_FREQUENCY, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0e,0x00,0x00 }, AV_CH_LOW_FREQUENCY_2, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Front Subwoofer + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x0f,0x00,0x00 }, AV_CH_TOP_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear Height + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x10,0x00,0x00 }, AV_CH_BACK_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Rear + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x11,0x00,0x00 }, AV_CH_BOTTOM_FRONT_LEFT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Left Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x12,0x00,0x00 }, AV_CH_BOTTOM_FRONT_RIGHT, AV_AUDIO_SERVICE_TYPE_MAIN }, // Right Below + { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x0d,0x03,0x02,0x01,0x30,0x01,0x13,0x00,0x00 }, AV_CH_BOTTOM_FRONT_CENTER, AV_AUDIO_SERVICE_TYPE_MAIN }, // Center Below + { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_AUDIO_SERVICE_TYPE_NB }, +}; + static MXFWrappingScheme mxf_get_wrapping_kind(UID *essence_container_ul) { int val; @@ -2274,12 +2414,12 @@ static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *des /* CDCI range metadata */ if (!descriptor->component_depth) return AVCOL_RANGE_UNSPECIFIED; - if (descriptor->black_ref_level == 0 && + if (descriptor->black_ref_level == 0 && descriptor->component_depth < 31 && descriptor->white_ref_level == ((1<component_depth) - 1) && (descriptor->color_range == (1<component_depth) || descriptor->color_range == ((1<component_depth) - 1))) return AVCOL_RANGE_JPEG; - if (descriptor->component_depth >= 8 && + if (descriptor->component_depth >= 8 && descriptor->component_depth < 31 && descriptor->black_ref_level == (1 <<(descriptor->component_depth - 4)) && descriptor->white_ref_level == (235<<(descriptor->component_depth - 8)) && descriptor->color_range == ((14<<(descriptor->component_depth - 4)) + 1)) @@ -2292,6 +2432,139 @@ static enum AVColorRange mxf_get_color_range(MXFContext *mxf, MXFDescriptor *des return AVCOL_RANGE_UNSPECIFIED; } +static int is_pcm(enum AVCodecID codec_id) +{ + /* we only care about "normal" PCM codecs until we get samples */ + return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; +} + +static int set_language(AVFormatContext *s, const char *rfc5646, AVDictionary **met) +{ + // language abbr should contain at least 2 chars + if (rfc5646 && strlen(rfc5646) > 1) { + char primary_tag[4] = + {rfc5646[0], rfc5646[1], rfc5646[2] != '-' ? rfc5646[2] : '\0', '\0'}; + + const char *iso6392 = ff_convert_lang_to(primary_tag, + AV_LANG_ISO639_2_BIBL); + if (iso6392) + return(av_dict_set(met, "language", iso6392, 0)); + } + return 0; +} + +static MXFMCASubDescriptor *find_mca_link_id(MXFContext *mxf, enum MXFMetadataSetType type, UID *mca_link_id) +{ + for (int k = 0; k < mxf->metadata_sets_count; k++) { + MXFMCASubDescriptor *group = (MXFMCASubDescriptor*)mxf->metadata_sets[k]; + if (group->meta.type == type && !memcmp(&group->mca_link_id, mca_link_id, 16)) + return group; + } + return NULL; +} + +static int parse_mca_labels(MXFContext *mxf, MXFTrack *source_track, MXFDescriptor *descriptor, AVStream *st) +{ + uint64_t routing[FF_SANE_NB_CHANNELS] = {0}; + char *language = NULL; + int ambigous_language = 0; + enum AVAudioServiceType service_type = AV_AUDIO_SERVICE_TYPE_NB; + int ambigous_service_type = 0; + int has_channel_label = 0; + + for (int i = 0; i < descriptor->sub_descriptors_count; i++) { + char *channel_language; + + MXFMCASubDescriptor *label = mxf_resolve_strong_ref(mxf, &descriptor->sub_descriptors_refs[i], AudioChannelLabelSubDescriptor); + if (label == NULL) + continue; + + has_channel_label = 1; + for (const MXFChannelOrderingUL* channel_ordering = mxf_channel_ordering; channel_ordering->uid[0]; channel_ordering++) { + if (IS_KLV_KEY(channel_ordering->uid, label->mca_label_dictionary_id)) { + int target_channel = label->mca_channel_id; + if (target_channel == 0 && descriptor->channels == 1) + target_channel = 1; + if (target_channel <= 0 || target_channel > descriptor->channels) { + av_log(mxf->fc, AV_LOG_ERROR, "AudioChannelLabelSubDescriptor has invalid MCA channel ID %d\n", target_channel); + return AVERROR_INVALIDDATA; + } + routing[target_channel - 1] = channel_ordering->layout_mask; + if (service_type == AV_AUDIO_SERVICE_TYPE_NB) + service_type = channel_ordering->service_type; + else if (service_type != channel_ordering->service_type) + ambigous_service_type = 1; + break; + } + } + + channel_language = label->language; + if (!channel_language) { + MXFMCASubDescriptor *group = find_mca_link_id(mxf, SoundfieldGroupLabelSubDescriptor, &label->soundfield_group_link_id); + if (group) { + channel_language = group->language; + if (!channel_language && group->group_of_soundfield_groups_link_id_count) { + MXFMCASubDescriptor *supergroup = find_mca_link_id(mxf, GroupOfSoundfieldGroupsLabelSubDescriptor, + group->group_of_soundfield_groups_link_id_refs); + if (supergroup) + channel_language = supergroup->language; + } + } + } + if (channel_language) { + if (language && strcmp(language, channel_language)) + ambigous_language = 1; + else + language = channel_language; + } + } + + if (language && !ambigous_language) { + int ret = set_language(mxf->fc, language, &st->metadata); + if (ret < 0) + return ret; + } + + if (service_type != AV_AUDIO_SERVICE_TYPE_NB && service_type != AV_AUDIO_SERVICE_TYPE_MAIN && !ambigous_service_type) { + enum AVAudioServiceType *ast; + uint8_t* side_data = av_stream_new_side_data(st, AV_PKT_DATA_AUDIO_SERVICE_TYPE, sizeof(*ast)); + if (!side_data) + return AVERROR(ENOMEM); + ast = (enum AVAudioServiceType*)side_data; + *ast = service_type; + } + + if (has_channel_label) { + uint64_t channel_layout = 0; + + for (int i = 0; i < descriptor->channels; i++) { + if (!routing[i]) { + av_log(mxf->fc, AV_LOG_WARNING, "Designation of audio channel %d in stream #%d is unknown or unsupported, " + "falling back to unknown channel layout\n", st->index, i); + return 0; + } + if (channel_layout & 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); + return 0; + } + if (routing[i] < channel_layout) { + av_log(mxf->fc, AV_LOG_WARNING, "stream #%d is not in in native channel order, " + "falling back to unknown channel layout\n", st->index); + return 0; + } + channel_layout |= routing[i]; + } + + av_assert0(descriptor->channels == av_get_channel_layout_nb_channels(channel_layout)); + + st->codecpar->channel_layout = channel_layout; + } + + return 0; +} + static int mxf_parse_structural_metadata(MXFContext *mxf) { MXFPackage *material_package = NULL; @@ -2688,6 +2961,15 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) sti->need_parsing = AVSTREAM_PARSE_FULL; } st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); + + if (descriptor->channels <= 0 || descriptor->channels >= FF_SANE_NB_CHANNELS) { + av_log(mxf->fc, AV_LOG_ERROR, "Invalid number of channels %d, must be less than %d\n", descriptor->channels, FF_SANE_NB_CHANNELS); + return AVERROR_INVALIDDATA; + } + + ret = parse_mca_labels(mxf, source_track, descriptor, st); + if (ret < 0) + return ret; } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { enum AVMediaType type; container_ul = mxf_get_codec_ul(mxf_data_essence_container_uls, essence_container_ul); @@ -2888,6 +3170,9 @@ static const MXFMetadataReadTableEntry mxf_metadata_read_table[] = { { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* VANC/VBI - SMPTE 436M */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5e,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* MPEG2AudioDescriptor */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x64,0x00 }, mxf_read_generic_descriptor, sizeof(MXFDescriptor), Descriptor }, /* DC Timed Text Descriptor */ + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6b,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), AudioChannelLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6c,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), SoundfieldGroupLabelSubDescriptor }, + { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x6d,0x00 }, mxf_read_mca_sub_descriptor, sizeof(MXFMCASubDescriptor), GroupOfSoundfieldGroupsLabelSubDescriptor }, { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3A,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Static Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x3B,0x00 }, mxf_read_track, sizeof(MXFTrack), Track }, /* Generic Track */ { { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x14,0x00 }, mxf_read_timecode_component, sizeof(MXFTimecodeComponent), TimecodeComponent }, @@ -3187,12 +3472,6 @@ static void mxf_compute_essence_containers(AVFormatContext *s) } } -static int is_pcm(enum AVCodecID codec_id) -{ - /* we only care about "normal" PCM codecs until we get samples */ - return codec_id >= AV_CODEC_ID_PCM_S16LE && codec_id < AV_CODEC_ID_PCM_S24DAUD; -} - static MXFIndexTable *mxf_find_index_table(MXFContext *mxf, int index_sid) { int i; diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c index c36ebef932..5e068c8220 100644 --- a/libavformat/mxfenc.c +++ b/libavformat/mxfenc.c @@ -32,6 +32,7 @@ * SMPTE 379M MXF Generic Container * SMPTE 381M Mapping MPEG Streams into the MXF Generic Container * SMPTE 422M Mapping JPEG 2000 Codestreams into the MXF Generic Container + * SMPTE ST2019-4 (2009 or later) Mapping VC-3 Coding Units into the MXF Generic Container * SMPTE RP210: SMPTE Metadata Dictionary * SMPTE RP224: Registry of SMPTE Universal Labels */ @@ -48,7 +49,6 @@ #include "libavutil/pixdesc.h" #include "libavutil/time_internal.h" #include "libavcodec/bytestream.h" -#include "libavcodec/dnxhddata.h" #include "libavcodec/dv_profile.h" #include "libavcodec/h264_ps.h" #include "libavcodec/golomb.h" @@ -181,8 +181,8 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x00,0x00,0x00 }, mxf_write_cdci_desc }, // DNxHD - { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, - { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 }, + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x0D,0x01,0x03,0x01,0x02,0x11,0x01,0x00 }, + { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x0C,0x00 }, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 }, mxf_write_cdci_desc }, // JPEG2000 @@ -421,6 +421,7 @@ typedef struct MXFContext { int track_instance_count; // used to generate MXFTrack uuids int cbr_index; ///< use a constant bitrate index uint8_t unused_tags[MXF_NUM_TAGS]; ///< local tags that we know will not be used + MXFStreamContext timecode_track_priv; } MXFContext; static void mxf_write_uuid(AVIOContext *pb, enum MXFMetadataSetType type, int value) @@ -2035,36 +2036,37 @@ static int mxf_parse_prores_frame(AVFormatContext *s, AVStream *st, AVPacket *pk } static const struct { - int cid; + uint16_t cid; + uint8_t interlaced; UID codec_ul; } mxf_dnxhd_codec_uls[] = { - { 1235, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH - { 1237, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED - { 1238, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH - { 1241, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH - { 1242, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED - { 1243, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH - { 1244, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR - { 1250, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit - { 1251, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH - { 1252, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED - { 1253, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW - { 1256, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444 - { 1258, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR - { 1259, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR - { 1260, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF - { 1270, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444 - { 1271, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX - { 1272, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ - { 1273, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ - { 1274, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB + { 1235, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x01,0x00,0x00 } }, // 1080p 10bit HIGH + { 1237, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x03,0x00,0x00 } }, // 1080p 8bit MED + { 1238, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x04,0x00,0x00 } }, // 1080p 8bit HIGH + { 1241, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x07,0x00,0x00 } }, // 1080i 10bit HIGH + { 1242, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x08,0x00,0x00 } }, // 1080i 8bit MED + { 1243, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x09,0x00,0x00 } }, // 1080i 8bit HIGH + { 1244, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x0a,0x00,0x00 } }, // 1080i 8bit TR + { 1250, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x10,0x00,0x00 } }, // 720p 10bit + { 1251, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x11,0x00,0x00 } }, // 720p 8bit HIGH + { 1252, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x12,0x00,0x00 } }, // 720p 8bit MED + { 1253, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x13,0x00,0x00 } }, // 720p 8bit LOW + { 1256, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x16,0x00,0x00 } }, // 1080p 10bit 444 + { 1258, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x18,0x00,0x00 } }, // 720p 8bit TR + { 1259, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x19,0x00,0x00 } }, // 1080p 8bit TR + { 1260, 1, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x1a,0x00,0x00 } }, // 1080i 8bit TR MBAFF + { 1270, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x24,0x00,0x00 } }, // DNXHR 444 + { 1271, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x25,0x00,0x00 } }, // DNXHR HQX + { 1272, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x26,0x00,0x00 } }, // DNXHR HQ + { 1273, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x27,0x00,0x00 } }, // DNXHR SQ + { 1274, 0, { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x71,0x28,0x00,0x00 } }, // DNXHR LB }; static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) { MXFContext *mxf = s->priv_data; MXFStreamContext *sc = st->priv_data; - int i, cid, frame_size = 0; + int i, cid; if (mxf->header_written) return 1; @@ -2076,6 +2078,7 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt for (i = 0; i < FF_ARRAY_ELEMS(mxf_dnxhd_codec_uls); i++) { if (cid == mxf_dnxhd_codec_uls[i].cid) { sc->codec_ul = &mxf_dnxhd_codec_uls[i].codec_ul; + sc->interlaced = mxf_dnxhd_codec_uls[i].interlaced; break; } } @@ -2091,15 +2094,6 @@ static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt if (!sc->component_depth) return 0; - if ((frame_size = avpriv_dnxhd_get_frame_size(cid)) == DNXHD_VARIABLE) { - frame_size = avpriv_dnxhd_get_hr_frame_size(cid, st->codecpar->width, st->codecpar->height); - } - if (frame_size < 0) - return 0; - - if ((sc->interlaced = avpriv_dnxhd_get_interlaced(cid)) < 0) - return 0; - if (cid >= 1270) { // RI raster av_reduce(&sc->aspect_ratio.num, &sc->aspect_ratio.den, st->codecpar->width, st->codecpar->height, @@ -2203,9 +2197,9 @@ static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt) static const struct { UID uid; int frame_size; - int profile; + uint8_t profile; uint8_t interlaced; - int intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored + int8_t intra_only; // 1 or 0 when there are separate UIDs for Long GOP and Intra, -1 when Intra/LGOP detection can be ignored } mxf_h264_codec_uls[] = { {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 0, 66, 0, -1 }, // AVC Baseline {{ 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x31,0x20,0x01 }, 0, 77, 0, -1 }, // AVC Main @@ -2500,16 +2494,13 @@ 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 int mxf_write_header(AVFormatContext *s) +static int mxf_init(AVFormatContext *s) { MXFContext *mxf = s->priv_data; int i, ret; uint8_t present[FF_ARRAY_ELEMS(mxf_essence_container_uls)] = {0}; int64_t timestamp = 0; - if (!s->nb_streams) - return -1; - if (s->oformat == &ff_mxf_opatom_muxer && s->nb_streams !=1) { av_log(s, AV_LOG_ERROR, "there must be exactly one stream for mxf opatom\n"); return -1; @@ -2684,6 +2675,12 @@ static int mxf_write_header(AVFormatContext *s) memcpy(sc->track_essence_element_key, mxf_essence_container_uls[sc->index].element_ul, 15); sc->track_essence_element_key[15] = present[sc->index]; + if (s->oformat == &ff_mxf_opatom_muxer && st->codecpar->codec_id == AV_CODEC_ID_DNXHD) { + // clip-wrapping requires 0x0D per ST2019-4:2009 or 0x06 per previous version ST2019-4:2008 + // we choose to use 0x06 instead 0x0D to be compatible with AVID systems + // and produce mxf files with the most relevant flavour for opatom + sc->track_essence_element_key[14] = 0x06; + } PRINT_KEY(s, "track essence element key", sc->track_essence_element_key); if (!present[sc->index]) @@ -2715,9 +2712,7 @@ static int mxf_write_header(AVFormatContext *s) mxf->timecode_track = av_mallocz(sizeof(*mxf->timecode_track)); if (!mxf->timecode_track) return AVERROR(ENOMEM); - mxf->timecode_track->priv_data = av_mallocz(sizeof(MXFStreamContext)); - if (!mxf->timecode_track->priv_data) - return AVERROR(ENOMEM); + mxf->timecode_track->priv_data = &mxf->timecode_track_priv; mxf->timecode_track->index = -1; return 0; @@ -3090,10 +3085,7 @@ static void mxf_deinit(AVFormatContext *s) av_freep(&mxf->index_entries); av_freep(&mxf->body_partition_offset); - if (mxf->timecode_track) { - av_freep(&mxf->timecode_track->priv_data); - av_freep(&mxf->timecode_track); - } + av_freep(&mxf->timecode_track); } static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flush) @@ -3105,9 +3097,9 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus stream_count += !!ffstream(s->streams[i])->last_in_packet_buffer; if (stream_count && (s->nb_streams == stream_count || flush)) { - PacketList *pktl = si->packet_buffer; + PacketListEntry *pktl = si->packet_buffer.head; if (s->nb_streams != stream_count) { - PacketList *last = NULL; + PacketListEntry *last = NULL; // find last packet in edit unit while (pktl) { if (!stream_count || pktl->pkt.stream_index == 0) @@ -3121,7 +3113,7 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus } // purge packet queue while (pktl) { - PacketList *next = pktl->next; + PacketListEntry *next = pktl->next; av_packet_unref(&pktl->pkt); av_freep(&pktl); pktl = next; @@ -3129,21 +3121,17 @@ static int mxf_interleave_get_packet(AVFormatContext *s, AVPacket *out, int flus if (last) last->next = NULL; else { - si->packet_buffer = NULL; - si->packet_buffer_end = NULL; + si->packet_buffer.head = NULL; + si->packet_buffer.tail = NULL; goto out; } - pktl = si->packet_buffer; + pktl = si->packet_buffer.head; } - *out = pktl->pkt; - av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", (*out).stream_index, (*out).dts); - si->packet_buffer = pktl->next; if (ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer == pktl) ffstream(s->streams[pktl->pkt.stream_index])->last_in_packet_buffer = NULL; - if (!si->packet_buffer) - si->packet_buffer_end = NULL; - av_freep(&pktl); + avpriv_packet_list_get(&si->packet_buffer, out); + av_log(s, AV_LOG_TRACE, "out st:%d dts:%"PRId64"\n", out->stream_index, out->dts); return 1; } else { out: @@ -3248,7 +3236,7 @@ const AVOutputFormat ff_mxf_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_MPEG2VIDEO, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, @@ -3264,7 +3252,7 @@ const AVOutputFormat ff_mxf_d10_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_MPEG2VIDEO, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, @@ -3281,7 +3269,7 @@ const AVOutputFormat ff_mxf_opatom_muxer = { .priv_data_size = sizeof(MXFContext), .audio_codec = AV_CODEC_ID_PCM_S16LE, .video_codec = AV_CODEC_ID_DNXHD, - .write_header = mxf_write_header, + .init = mxf_init, .write_packet = mxf_write_packet, .write_trailer = mxf_write_footer, .deinit = mxf_deinit, diff --git a/libavformat/nullenc.c b/libavformat/nullenc.c index 7354913726..d4769d5920 100644 --- a/libavformat/nullenc.c +++ b/libavformat/nullenc.c @@ -20,6 +20,7 @@ */ #include "avformat.h" +#include "internal.h" static int null_write_packet(struct AVFormatContext *s, AVPacket *pkt) { @@ -33,4 +34,5 @@ const AVOutputFormat ff_null_muxer = { .video_codec = AV_CODEC_ID_WRAPPED_AVFRAME, .write_packet = null_write_packet, .flags = AVFMT_VARIABLE_FPS | AVFMT_NOFILE | AVFMT_NOTIMESTAMPS, + .interleave_packet = ff_interleave_packet_passthrough, }; diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index 7977980935..585ce953ca 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -70,11 +70,11 @@ static int find_expected_header(AVCodecParameters *p, int size, int key_frame, else if (sample_rate < (44100 + 48000) / 2) sample_rate_index = 0; else sample_rate_index = 1; - sample_rate = avpriv_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); + sample_rate = ff_mpa_freq_tab[sample_rate_index] >> (lsf + mpeg25); for (bitrate_index = 2; bitrate_index < 30; bitrate_index++) { frame_size = - avpriv_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; + ff_mpa_bitrate_tab[lsf][layer - 1][bitrate_index >> 1]; frame_size = (frame_size * 144000) / (sample_rate << lsf) + (bitrate_index & 1); diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c index 77e8d301b2..e1ef510892 100644 --- a/libavformat/oggparsevorbis.c +++ b/libavformat/oggparsevorbis.c @@ -320,10 +320,9 @@ static int vorbis_header(AVFormatContext *s, int idx) return priv->vp ? 0 : AVERROR_INVALIDDATA; priv->len[pkt_type >> 1] = os->psize; - priv->packet[pkt_type >> 1] = av_mallocz(os->psize); + priv->packet[pkt_type >> 1] = av_memdup(os->buf + os->pstart, os->psize); if (!priv->packet[pkt_type >> 1]) return AVERROR(ENOMEM); - memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize); if (os->buf[os->pstart] == 1) { const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */ unsigned blocksize, bs0, bs1; diff --git a/libavformat/omadec.c b/libavformat/omadec.c index a727cc4d66..4c418a5ff2 100644 --- a/libavformat/omadec.c +++ b/libavformat/omadec.c @@ -108,7 +108,6 @@ static void hex_log(AVFormatContext *s, int level, if (av_log_get_level() < level) return; ff_data_to_hex(buf, value, len, 1); - buf[len << 1] = '\0'; av_log(s, level, "%s: %s\n", name, buf); } diff --git a/libavformat/options.c b/libavformat/options.c index 753aa9b8dc..1634388acb 100644 --- a/libavformat/options.c +++ b/libavformat/options.c @@ -146,9 +146,9 @@ 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); } -static void io_close_default(AVFormatContext *s, AVIOContext *pb) +static int io_close2_default(AVFormatContext *s, AVIOContext *pb) { - avio_close(pb); + return avio_close(pb); } AVFormatContext *avformat_alloc_context(void) @@ -162,7 +162,8 @@ AVFormatContext *avformat_alloc_context(void) s = &si->pub; s->av_class = &av_format_context_class; s->io_open = io_open_default; - s->io_close = io_close_default; + s->io_close = ff_format_io_close_default; + s->io_close2= io_close2_default; av_opt_set_defaults(s); @@ -174,7 +175,6 @@ AVFormatContext *avformat_alloc_context(void) } si->offset = AV_NOPTS_VALUE; - si->raw_packet_buffer_remaining_size = RAW_PACKET_BUFFER_SIZE; si->shortest_end = AV_NOPTS_VALUE; return s; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index b108aa6c7e..948fae411f 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -93,17 +93,17 @@ const AVClass *ff_urlcontext_child_class_iterate(void **iter) const char *avio_enum_protocols(void **opaque, int output) { - const URLProtocol **p = *opaque; + uintptr_t i; - p = p ? p + 1 : url_protocols; - *opaque = p; - if (!*p) { - *opaque = NULL; - return NULL; + for (i = (uintptr_t)*opaque; url_protocols[i]; i++) { + const URLProtocol *p = url_protocols[i]; + if ((output && p->url_write) || (!output && p->url_read)) { + *opaque = (void*)(uintptr_t)(i + 1); + return p->name; + } } - if ((output && (*p)->url_write) || (!output && (*p)->url_read)) - return (*p)->name; - return avio_enum_protocols(opaque, output); + *opaque = NULL; + return NULL; } const AVClass *avio_protocol_get_class(const char *name) diff --git a/libavformat/rawenc.c b/libavformat/rawenc.c index 15e7051873..4bbae7717b 100644 --- a/libavformat/rawenc.c +++ b/libavformat/rawenc.c @@ -341,9 +341,9 @@ const AVOutputFormat ff_h263_muxer = { #endif #if CONFIG_H264_MUXER -static int h264_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int h264_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL); @@ -364,9 +364,9 @@ const AVOutputFormat ff_h264_muxer = { #endif #if CONFIG_HEVC_MUXER -static int hevc_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int hevc_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; if (pkt->size >= 5 && AV_RB32(pkt->data) != 0x0000001 && AV_RB24(pkt->data) != 0x000001) return ff_stream_add_bitstream_filter(st, "hevc_mp4toannexb", NULL); @@ -468,9 +468,9 @@ const AVOutputFormat ff_mpeg2video_muxer = { #endif #if CONFIG_OBU_MUXER -static int obu_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int obu_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { - AVStream *st = s->streams[0]; return ff_stream_add_bitstream_filter(st, "av1_metadata", "td=insert"); } diff --git a/libavformat/rawvideodec.c b/libavformat/rawvideodec.c index 5049a29b9c..7b1a534452 100644 --- a/libavformat/rawvideodec.c +++ b/libavformat/rawvideodec.c @@ -33,6 +33,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) { @@ -40,6 +42,7 @@ static int rawvideo_read_header(AVFormatContext *ctx) enum AVPixelFormat pix_fmt; AVStream *st; int packet_size; + int ret; st = avformat_new_stream(ctx, NULL); if (!st) @@ -49,20 +52,63 @@ 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); + ret = av_image_check_size(s->width, s->height, 0, ctx); + if (ret < 0) + return ret; + st->codecpar->width = s->width; st->codecpar->height = s->height; + + if (ctx->iformat->raw_codec_id == AV_CODEC_ID_BITPACKED) { + unsigned int pgroup; /* size of the pixel group in bytes */ + unsigned int xinc; + const AVPixFmtDescriptor *desc; + int tag; + + desc = av_pix_fmt_desc_get(pix_fmt); + st->codecpar->bits_per_coded_sample = av_get_bits_per_pixel(desc); + if (pix_fmt == AV_PIX_FMT_YUV422P10) { + tag = MKTAG('U', 'Y', 'V', 'Y'); + pgroup = 5; + xinc = 2; + } else if (pix_fmt == AV_PIX_FMT_UYVY422) { + tag = MKTAG('U', 'Y', 'V', 'Y'); + pgroup = 4; + xinc = 2; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + av_log(ctx, AV_LOG_ERROR, "unsupported format: %s for bitpacked.\n", + s->pixel_format); + return AVERROR(EINVAL); + } + 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) + return packet_size; + } + if (packet_size == 0) + return AVERROR(EINVAL); + st->codecpar->format = pix_fmt; - packet_size = av_image_get_buffer_size(st->codecpar->format, s->width, s->height, 1); - if (packet_size < 0) - return packet_size; ctx->packet_size = packet_size; st->codecpar->bit_rate = av_rescale_q(ctx->packet_size, (AVRational){8,1}, st->time_base); @@ -87,8 +133,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 }, }; @@ -111,3 +158,59 @@ const AVInputFormat ff_rawvideo_demuxer = { .raw_codec_id = AV_CODEC_ID_RAWVIDEO, .priv_class = &rawvideo_demuxer_class, }; + +static const AVClass bitpacked_demuxer_class = { + .class_name = "bitpacked demuxer", + .item_name = av_default_item_name, + .option = rawvideo_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +#if CONFIG_BITPACKED_DEMUXER +const AVInputFormat ff_bitpacked_demuxer = { + .name = "bitpacked", + .long_name = NULL_IF_CONFIG_SMALL("Bitpacked"), + .priv_data_size = sizeof(RawVideoDemuxerContext), + .read_header = rawvideo_read_header, + .read_packet = rawvideo_read_packet, + .flags = AVFMT_GENERIC_INDEX, + .extensions = "bitpacked", + .raw_codec_id = AV_CODEC_ID_BITPACKED, + .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/rtmpproto.c b/libavformat/rtmpproto.c index b14d23b919..34020bc383 100644 --- a/libavformat/rtmpproto.c +++ b/libavformat/rtmpproto.c @@ -1663,7 +1663,6 @@ static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce) av_md5_update(md5, rt->password, strlen(rt->password)); av_md5_final(md5, hash); ff_data_to_hex(hashstr1, hash, 16, 1); - hashstr1[32] = '\0'; av_md5_init(md5); av_md5_update(md5, method, strlen(method)); @@ -1673,7 +1672,6 @@ static int do_llnw_auth(RTMPContext *rt, const char *user, const char *nonce) av_md5_update(md5, "/_definst_", strlen("/_definst_")); av_md5_final(md5, hash); ff_data_to_hex(hashstr2, hash, 16, 1); - hashstr2[32] = '\0'; av_md5_init(md5); av_md5_update(md5, hashstr1, strlen(hashstr1)); diff --git a/libavformat/rtp.c b/libavformat/rtp.c index 38e234391b..c536a6f082 100644 --- a/libavformat/rtp.c +++ b/libavformat/rtp.c @@ -87,8 +87,8 @@ int ff_rtp_get_codec_info(AVCodecParameters *par, int payload_type) return -1; } -int ff_rtp_get_payload_type(AVFormatContext *fmt, - AVCodecParameters *par, int idx) +int ff_rtp_get_payload_type(const AVFormatContext *fmt, + const AVCodecParameters *par, int idx) { int i; const AVOutputFormat *ofmt = fmt ? fmt->oformat : NULL; diff --git a/libavformat/rtp.h b/libavformat/rtp.h index 389b824223..0c0e6089d7 100644 --- a/libavformat/rtp.h +++ b/libavformat/rtp.h @@ -38,8 +38,8 @@ * @param idx The stream index * @return The payload type (the 'PT' field in the RTP header). */ -int ff_rtp_get_payload_type(AVFormatContext *fmt, AVCodecParameters *par, - int idx); +int ff_rtp_get_payload_type(const AVFormatContext *fmt, + const AVCodecParameters *par, int idx); /** * Initialize a codec context based on the payload type. diff --git a/libavformat/rtpdec_jpeg.c b/libavformat/rtpdec_jpeg.c index b32d074136..81036247c1 100644 --- a/libavformat/rtpdec_jpeg.c +++ b/libavformat/rtpdec_jpeg.c @@ -144,14 +144,14 @@ static int jpeg_create_header(uint8_t *buf, int size, uint32_t type, uint32_t w, bytestream2_put_be16(&pbc, 0); dht_size = 2; - dht_size += jpeg_create_huffman_table(&pbc, 0, 0,avpriv_mjpeg_bits_dc_luminance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 0, 1, avpriv_mjpeg_bits_dc_chrominance, - avpriv_mjpeg_val_dc); - dht_size += jpeg_create_huffman_table(&pbc, 1, 0, avpriv_mjpeg_bits_ac_luminance, - avpriv_mjpeg_val_ac_luminance); - dht_size += jpeg_create_huffman_table(&pbc, 1, 1, avpriv_mjpeg_bits_ac_chrominance, - avpriv_mjpeg_val_ac_chrominance); + dht_size += jpeg_create_huffman_table(&pbc, 0, 0,ff_mjpeg_bits_dc_luminance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 0, 1, ff_mjpeg_bits_dc_chrominance, + ff_mjpeg_val_dc); + dht_size += jpeg_create_huffman_table(&pbc, 1, 0, ff_mjpeg_bits_ac_luminance, + ff_mjpeg_val_ac_luminance); + dht_size += jpeg_create_huffman_table(&pbc, 1, 1, ff_mjpeg_bits_ac_chrominance, + ff_mjpeg_val_ac_chrominance); AV_WB16(dht_size_ptr, dht_size); /* SOF0 */ diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c index f50cad76d2..8e73c07838 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; @@ -55,9 +57,42 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data) if (data->depth == 8) { data->pgroup = 4; pixfmt = AV_PIX_FMT_UYVY422; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; } else if (data->depth == 10) { data->pgroup = 5; pixfmt = AV_PIX_FMT_YUV422P10; + stream->codecpar->codec_id = AV_CODEC_ID_BITPACKED; + } else { + return AVERROR_INVALIDDATA; + } + } else if (!strncmp(data->sampling, "YCbCr-4:2:0", 11)) { + tag = MKTAG('I', '4', '2', '0'); + data->xinc = 4; + + if (data->depth == 8) { + data->pgroup = 6; + pixfmt = AV_PIX_FMT_YUV420P; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + return AVERROR_INVALIDDATA; + } + } else if (!strncmp(data->sampling, "RGB", 3)) { + tag = MKTAG('R', 'G', 'B', 24); + if (data->depth == 8) { + data->xinc = 1; + data->pgroup = 3; + pixfmt = AV_PIX_FMT_RGB24; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + } else { + return AVERROR_INVALIDDATA; + } + } else if (!strncmp(data->sampling, "BGR", 3)) { + tag = MKTAG('B', 'G', 'R', 24); + if (data->depth == 8) { + data->xinc = 1; + data->pgroup = 3; + pixfmt = AV_PIX_FMT_BGR24; + stream->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; } else { return AVERROR_INVALIDDATA; } @@ -71,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; @@ -91,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); @@ -162,17 +204,20 @@ 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); - } + pkt->stream_index = stream_index; + 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; + return ret; } static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, @@ -180,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; @@ -233,10 +278,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; @@ -244,9 +291,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; @@ -268,7 +318,7 @@ static int rfc4175_handle_packet(AVFormatContext *ctx, PayloadContext *data, const RTPDynamicProtocolHandler ff_rfc4175_rtp_handler = { .enc_name = "raw", .codec_type = AVMEDIA_TYPE_VIDEO, - .codec_id = AV_CODEC_ID_BITPACKED, + .codec_id = AV_CODEC_ID_NONE, .priv_data_size = sizeof(PayloadContext), .parse_sdp_a_line = rfc4175_parse_sdp_line, .parse_packet = rfc4175_handle_packet, diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c index 2a1c176066..6be67b5885 100644 --- a/libavformat/rtpenc.c +++ b/libavformat/rtpenc.c @@ -84,6 +84,8 @@ static int is_supported(enum AVCodecID id) case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_SPEEX: case AV_CODEC_ID_OPUS: + case AV_CODEC_ID_RAWVIDEO: + case AV_CODEC_ID_BITPACKED: return 1; default: return 0; @@ -619,6 +621,15 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt) case AV_CODEC_ID_MJPEG: ff_rtp_send_jpeg(s1, pkt->data, size); break; + case AV_CODEC_ID_BITPACKED: + 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 62dc9ab10a..9c8ad14a53 100644 --- a/libavformat/rtpenc.h +++ b/libavformat/rtpenc.h @@ -95,6 +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, 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_jpeg.c b/libavformat/rtpenc_jpeg.c index 38eb2e68eb..91116832da 100644 --- a/libavformat/rtpenc_jpeg.c +++ b/libavformat/rtpenc_jpeg.c @@ -101,8 +101,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) switch (buf[i + 1]) { case 0x00: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1; i += 29; dht_size -= 29; @@ -113,8 +113,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x01: if ( dht_size >= 29 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_dc_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_dc, 12)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_dc_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_dc, 12)) { default_huffman_tables |= 1 << 1; i += 29; dht_size -= 29; @@ -125,8 +125,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x10: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_luminance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_luminance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_luminance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_luminance, 162)) { default_huffman_tables |= 1 << 2; i += 179; dht_size -= 179; @@ -137,8 +137,8 @@ void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buf, int size) break; case 0x11: if ( dht_size >= 179 - && !memcmp(buf + i + 2, avpriv_mjpeg_bits_ac_chrominance + 1, 16) - && !memcmp(buf + i + 18, avpriv_mjpeg_val_ac_chrominance, 162)) { + && !memcmp(buf + i + 2, ff_mjpeg_bits_ac_chrominance + 1, 16) + && !memcmp(buf + i + 18, ff_mjpeg_val_ac_chrominance, 162)) { default_huffman_tables |= 1 << 3; i += 179; dht_size -= 179; diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c new file mode 100644 index 0000000000..257d072cd3 --- /dev/null +++ b/libavformat/rtpenc_rfc4175.c @@ -0,0 +1,139 @@ +/* + * RTP Packetization of RAW video (RFC4175) + * 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 "avformat.h" +#include "rtpenc.h" + +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 i = 0; + int offset = 0; + + s->timestamp = s->cur_timestamp; + switch (s1->streams[0]->codecpar->format) { + case AV_PIX_FMT_UYVY422: + xinc = 2; + yinc = 1 << interlaced; + pgroup = 4; + break; + case AV_PIX_FMT_YUV422P10: + xinc = 2; + yinc = 1 << interlaced; + pgroup = 5; + break; + case AV_PIX_FMT_YUV420P: + xinc = 4; + yinc = 1 << interlaced; + pgroup = 6; + break; + case AV_PIX_FMT_RGB24: + xinc = 1; + yinc = 1 << interlaced; + pgroup = 3; + break; + case AV_PIX_FMT_BGR24: + xinc = 1; + yinc = 1 << interlaced; + pgroup = 3; + break; + default: + return; + } + + while (i < height) { + int left = s->max_payload_size; + uint8_t *dest = s->buf; + uint8_t *headers; + const int head_size = 6; + int next_line; + int length, cont, pixels; + + /* Extended Sequence Number */ + *dest++ = 0; + *dest++ = 0; + left -= 2; + + headers = dest; + do { + int l_line; + + pixels = width - offset; + length = (pixels * pgroup) / xinc; + + left -= head_size; + if (left >= length) { + next_line = 1; + } else { + pixels = (left / pgroup) * xinc; + length = (pixels * pgroup) / xinc; + next_line = 0; + } + left -= length; + + /* Length */ + *dest++ = (length >> 8) & 0xff; + *dest++ = length & 0xff; + + /* Line No */ + 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; + /* Offset and Continuation marker */ + *dest++ = ((offset >> 8) & 0x7f) | cont; + *dest++ = offset & 0xff; + + if (next_line) + offset = 0; + else + offset += pixels; + } 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; + memcpy (dest, buf + copy_offset, length); + dest += length; + } while (cont); + + ff_rtp_send_data (s1, s->buf, s->max_payload_size - left, i >= height); + } +} diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 7dd6042158..c92cda63bb 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -61,6 +61,7 @@ typedef struct RTPContext { char *block; char *fec_options_str; int64_t rw_timeout; + char *localaddr; } RTPContext; #define OFFSET(x) offsetof(RTPContext, x) @@ -80,6 +81,7 @@ static const AVOption options[] = { { "sources", "Source list", OFFSET(sources), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { "block", "Block list", OFFSET(block), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { "fec", "FEC", OFFSET(fec_options_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = E }, + { "localaddr", "Local address", OFFSET(localaddr), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = D|E }, { NULL } }; @@ -173,6 +175,7 @@ static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const static void build_udp_url(RTPContext *s, char *buf, int buf_size, const char *hostname, + const char *localaddr, int port, int local_port, const char *include_sources, const char *exclude_sources) @@ -195,6 +198,8 @@ static void build_udp_url(RTPContext *s, url_add_option(buf, buf_size, "sources=%s", include_sources); if (exclude_sources && exclude_sources[0]) url_add_option(buf, buf_size, "block=%s", exclude_sources); + if (localaddr && localaddr[0]) + url_add_option(buf, buf_size, "localaddr=%s", localaddr); } /** @@ -284,6 +289,12 @@ static int rtp_open(URLContext *h, const char *uri, int flags) ff_ip_parse_blocks(h, s->block, &s->filters); block = s->block; } + if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { + av_freep(&s->localaddr); + s->localaddr = av_strdup(buf); + if (!s->localaddr) + goto fail; + } } if (s->rw_timeout >= 0) h->rw_timeout = s->rw_timeout; @@ -314,7 +325,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) for (i = 0; i < max_retry_count; i++) { build_udp_url(s, buf, sizeof(buf), - hostname, rtp_port, s->local_rtpport, + hostname, s->localaddr, rtp_port, s->local_rtpport, sources, block); if (ffurl_open_whitelist(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0) @@ -328,7 +339,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) if (s->local_rtcpport < 0) { s->local_rtcpport = s->local_rtpport + 1; build_udp_url(s, buf, sizeof(buf), - hostname, s->rtcp_port, s->local_rtcpport, + hostname, s->localaddr, s->rtcp_port, s->local_rtcpport, sources, block); if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback, NULL, @@ -339,7 +350,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) break; } build_udp_url(s, buf, sizeof(buf), - hostname, s->rtcp_port, s->local_rtcpport, + hostname, s->localaddr, s->rtcp_port, s->local_rtcpport, sources, block); if (ffurl_open_whitelist(&s->rtcp_hd, buf, rtcpflags, &h->interrupt_callback, NULL, h->protocol_whitelist, h->protocol_blacklist, h) < 0) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index a1aa969cad..70c18941ca 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -105,6 +105,7 @@ static const AVOption sdp_options[] = { { "custom_io", "use custom I/O", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, { "rtcp_to_source", "send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" }, { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC }, + { "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, @@ -113,6 +114,7 @@ static const AVOption sdp_options[] = { static const AVOption rtp_options[] = { RTSP_FLAG_OPTS("rtp_flags", "set RTP flags"), { "listen_timeout", "set maximum timeout (in seconds) to wait for incoming connections", OFFSET(stimeout), AV_OPT_TYPE_DURATION, {.i64 = READ_PACKET_TIMEOUT_S*1000000}, INT_MIN, INT64_MAX, DEC }, + { "localaddr", "local address", OFFSET(localaddr),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, \ RTSP_MEDIATYPE_OPTS("allowed_media_types", "set media types to accept from the server"), COMMON_OPTS(), { NULL }, @@ -125,6 +127,8 @@ static AVDictionary *map_to_opts(RTSPState *rt) av_dict_set_int(&opts, "buffer_size", rt->buffer_size, 0); av_dict_set_int(&opts, "pkt_size", rt->pkt_size, 0); + if (rt->localaddr && rt->localaddr[0]) + av_dict_set(&opts, "localaddr", rt->localaddr, 0); return opts; } @@ -242,6 +246,7 @@ static void finalize_rtp_handler_init(AVFormatContext *s, RTSPStream *rtsp_st, } } +#if CONFIG_RTSP_DEMUXER static int init_satip_stream(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -270,6 +275,7 @@ static int init_satip_stream(AVFormatContext *s) } return 0; } +#endif /* parse the rtpmap description: /[/] */ static int sdp_parse_rtpmap(AVFormatContext *s, @@ -383,10 +389,9 @@ static void copy_default_source_addrs(struct RTSPSource **addrs, int count, int i; for (i = 0; i < count; i++) { rtsp_src = addrs[i]; - rtsp_src2 = av_malloc(sizeof(*rtsp_src2)); + rtsp_src2 = av_memdup(rtsp_src, sizeof(*rtsp_src)); if (!rtsp_src2) continue; - memcpy(rtsp_src2, rtsp_src, sizeof(*rtsp_src)); dynarray_add(dest, dest_count, rtsp_src2); } } @@ -1142,7 +1147,7 @@ void ff_rtsp_parse_line(AVFormatContext *s, } /* skip a RTP/TCP interleaved packet */ -void ff_rtsp_skip_packet(AVFormatContext *s) +int ff_rtsp_skip_packet(AVFormatContext *s) { RTSPState *rt = s->priv_data; int ret, len, len1; @@ -1150,7 +1155,7 @@ void ff_rtsp_skip_packet(AVFormatContext *s) ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) - return; + return ret < 0 ? ret : AVERROR(EIO); len = AV_RB16(buf + 1); av_log(s, AV_LOG_TRACE, "skipping RTP packet len=%d\n", len); @@ -1162,9 +1167,11 @@ void ff_rtsp_skip_packet(AVFormatContext *s) len1 = sizeof(buf); ret = ffurl_read_complete(rt->rtsp_hd, buf, len1); if (ret != len1) - return; + return ret < 0 ? ret : AVERROR(EIO); len -= len1; } + + return 0; } int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, @@ -1175,8 +1182,8 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, char buf[MAX_URL_SIZE], buf1[MAX_URL_SIZE], *q; unsigned char ch; const char *p; - int ret, content_length, line_count = 0, request = 0; - unsigned char *content = NULL; + int ret, content_length, line_count, request; + unsigned char *content; start: line_count = 0; @@ -1192,14 +1199,17 @@ start: ret = ffurl_read_complete(rt->rtsp_hd, &ch, 1); av_log(s, AV_LOG_TRACE, "ret=%d c=%02x [%c]\n", ret, ch, ch); if (ret != 1) - return AVERROR_EOF; + return ret < 0 ? ret : AVERROR(EIO); if (ch == '\n') break; if (ch == '$' && q == buf) { if (return_on_interleaved_data) { return 1; - } else - ff_rtsp_skip_packet(s); + } else { + ret = ff_rtsp_skip_packet(s); + if (ret < 0) + return ret; + } } else if (ch != '\r') { if ((q - buf) < sizeof(buf) - 1) *q++ = ch; @@ -1242,8 +1252,10 @@ start: content = av_malloc(content_length + 1); if (!content) return AVERROR(ENOMEM); - if (ffurl_read_complete(rt->rtsp_hd, content, content_length) != content_length) - return AVERROR(EIO); + if ((ret = ffurl_read_complete(rt->rtsp_hd, content, content_length)) != content_length) { + av_freep(&content); + return ret < 0 ? ret : AVERROR(EIO); + } content[content_length] = '\0'; } if (content_ptr) @@ -1996,6 +2008,7 @@ redirect: #endif /* CONFIG_RTSP_DEMUXER || CONFIG_RTSP_MUXER */ #if CONFIG_RTPDEC +#if CONFIG_RTSP_DEMUXER static int parse_rtsp_message(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -2018,6 +2031,7 @@ static int parse_rtsp_message(AVFormatContext *s) return 0; } +#endif static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, uint8_t *buf, int buf_size, int64_t wait_end) @@ -2369,9 +2383,9 @@ static int sdp_read_header(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPStream *rtsp_st; - int size, i, err; - char *content; + int i, err; char url[MAX_URL_SIZE]; + AVBPrint bp; if (!ff_network_init()) return AVERROR(EIO); @@ -2382,22 +2396,15 @@ static int sdp_read_header(AVFormatContext *s) rt->lower_transport = RTSP_LOWER_TRANSPORT_CUSTOM; /* read the whole sdp file */ - /* XXX: better loading */ - content = av_malloc(SDP_MAX_SIZE); - if (!content) { + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); + err = avio_read_to_bprint(s->pb, &bp, INT_MAX); + if (err < 0 ) { ff_network_close(); - return AVERROR(ENOMEM); + av_bprint_finalize(&bp, NULL); + return err; } - size = avio_read(s->pb, content, SDP_MAX_SIZE - 1); - if (size <= 0) { - av_free(content); - ff_network_close(); - return AVERROR_INVALIDDATA; - } - content[size] ='\0'; - - err = ff_sdp_parse(s, content); - av_freep(&content); + err = ff_sdp_parse(s, bp.str); + av_bprint_finalize(&bp, NULL); if (err) goto fail; /* open each RTP stream */ @@ -2407,6 +2414,8 @@ static int sdp_read_header(AVFormatContext *s) if (!(rt->rtsp_flags & RTSP_FLAG_CUSTOM_IO)) { AVDictionary *opts = map_to_opts(rt); + char buf[MAX_URL_SIZE]; + const char *p; err = getnameinfo((struct sockaddr*) &rtsp_st->sdp_ip, sizeof(rtsp_st->sdp_ip), @@ -2424,6 +2433,11 @@ static int sdp_read_header(AVFormatContext *s) rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0, rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0); + p = strchr(s->url, '?'); + if (p && av_find_info_tag(buf, sizeof(buf), "localaddr", p)) + av_strlcatf(url, sizeof(url), "&localaddr=%s", buf); + else if (rt->localaddr && rt->localaddr[0]) + av_strlcatf(url, sizeof(url), "&localaddr=%s", rt->localaddr); append_source_addrs(url, sizeof(url), "sources", rtsp_st->nb_include_source_addrs, rtsp_st->include_source_addrs); diff --git a/libavformat/rtsp.h b/libavformat/rtsp.h index 4ec974ed73..8b64e29d70 100644 --- a/libavformat/rtsp.h +++ b/libavformat/rtsp.h @@ -419,6 +419,7 @@ typedef struct RTSPState { char default_lang[4]; int buffer_size; int pkt_size; + char *localaddr; } RTSPState; #define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - @@ -559,8 +560,10 @@ int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply, /** * Skip a RTP/TCP interleaved packet. + * + * @return 0 on success, < 0 on failure. */ -void ff_rtsp_skip_packet(AVFormatContext *s); +int ff_rtsp_skip_packet(AVFormatContext *s); /** * Connect to the RTSP server and set up the individual media streams. diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 0e91e3e315..2ada29a2d3 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -172,7 +172,7 @@ static int rtsp_read_announce(AVFormatContext *s) { RTSPState *rt = s->priv_data; RTSPMessageHeader request = { 0 }; - char sdp[SDP_MAX_SIZE]; + char *sdp; int ret; ret = rtsp_read_request(s, &request, "ANNOUNCE"); @@ -185,18 +185,24 @@ static int rtsp_read_announce(AVFormatContext *s) rtsp_send_reply(s, RTSP_STATUS_SERVICE, NULL, request.seq); return AVERROR_OPTION_NOT_FOUND; } - if (request.content_length && request.content_length < sizeof(sdp) - 1) { + if (request.content_length) { + sdp = av_malloc(request.content_length + 1); + if (!sdp) + return AVERROR(ENOMEM); + /* Read SDP */ if (ffurl_read_complete(rt->rtsp_hd, sdp, request.content_length) < request.content_length) { av_log(s, AV_LOG_ERROR, "Unable to get complete SDP Description in ANNOUNCE\n"); rtsp_send_reply(s, RTSP_STATUS_INTERNAL, NULL, request.seq); + av_free(sdp); return AVERROR(EIO); } sdp[request.content_length] = '\0'; av_log(s, AV_LOG_VERBOSE, "SDP: %s\n", sdp); ret = ff_sdp_parse(s, sdp); + av_free(sdp); if (ret) return ret; rtsp_send_reply(s, RTSP_STATUS_OK, NULL, request.seq); diff --git a/libavformat/rtspenc.c b/libavformat/rtspenc.c index e0fed1eebe..2a00b3e18d 100644 --- a/libavformat/rtspenc.c +++ b/libavformat/rtspenc.c @@ -200,8 +200,11 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) ret = ff_rtsp_read_reply(s, &reply, NULL, 1, NULL); if (ret < 0) return AVERROR(EPIPE); - if (ret == 1) - ff_rtsp_skip_packet(s); + if (ret == 1) { + ret = ff_rtsp_skip_packet(s); + if (ret < 0) + return ret; + } /* XXX: parse message */ if (rt->state != RTSP_STATE_STREAMING) return AVERROR(EPIPE); diff --git a/libavformat/scd.c b/libavformat/scd.c new file mode 100644 index 0000000000..0ed5322a14 --- /dev/null +++ b/libavformat/scd.c @@ -0,0 +1,378 @@ +/* + * Square Enix SCD demuxer + * Copyright (C) 2021 Zane van Iperen (zane@zanevaniperen.com) + * + * Based off documentation: + * http://ffxivexplorer.fragmenterworks.com/research/scd%20files.txt + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libavutil/avstring.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/internal.h" +#include "libavutil/macros.h" +#include "libavutil/avassert.h" +#include "libavformat/internal.h" +#include "avformat.h" + +#define SCD_MAGIC ((uint64_t)MKBETAG('S', 'E', 'D', 'B') << 32 | \ + MKBETAG('S', 'S', 'C', 'F')) +#define SCD_MIN_HEADER_SIZE 20 +#define SCD_OFFSET_HEADER_SIZE 28 +#define SCD_TRACK_HEADER_SIZE 32 + +#define SCD_TRACK_ID_PCM 0 +#define SCD_TRACK_ID_OGG 6 +#define SCD_TRACK_ID_MP3 7 +#define SCD_TRACK_ID_MS_ADPCM 12 + +typedef struct SCDOffsetTable { + uint16_t count; + uint32_t offset; + uint32_t *entries; +} SCDOffsetTable; + +typedef struct SCDHeader { + uint64_t magic; /* SEDBSSCF */ + uint32_t version; /* Verison number. We only know about 3. */ + uint16_t unk1; /* Unknown, 260 in Drakengard 3, 1024 in FFXIV. */ + uint16_t header_size; /* Total size of this header. */ + uint32_t file_size; /* Is often 0, just ignore it. */ + + SCDOffsetTable table0; /* Table 0, no idea. 56 uint32's/entry. */ + SCDOffsetTable table1; /* Table 1, contains the track info. */ + SCDOffsetTable table2; /* Table 2, no idea. 40 uint32's/entry. */ + uint16_t unk2; /* Unknown, not a count. */ + uint32_t unk3; /* Unknown, not an offset. */ + uint32_t unk4; /* Unknown, offset to offset. */ +} SCDHeader; + +typedef struct SCDTrackHeader { + uint32_t length; + uint32_t num_channels; + uint32_t sample_rate; + uint32_t data_type; + uint32_t loop_start; + uint32_t loop_end; + uint32_t data_offset; /* Offset to data + this header. */ + uint32_t aux_count; + + uint32_t absolute_offset; + uint32_t bytes_read; +} SCDTrackHeader; + +typedef struct SCDDemuxContext { + SCDHeader hdr; + SCDTrackHeader *tracks; + int current_track; +} SCDDemuxContext; + +static int scd_probe(const AVProbeData *p) +{ + if (AV_RB64(p->buf) != SCD_MAGIC) + return 0; + + return AVPROBE_SCORE_MAX; +} + +static int scd_read_table(AVFormatContext *s, SCDOffsetTable *table) +{ + int64_t ret; + + if ((ret = avio_seek(s->pb, table->offset, SEEK_SET)) < 0) + return ret; + + if ((table->entries = av_calloc(table->count, sizeof(uint32_t))) == NULL) + return ret; + + if ((ret = avio_read(s->pb, (unsigned char*)table->entries, table->count * sizeof(uint32_t))) < 0) + return ret; + + for (size_t i = 0; i < table->count; i++) + table->entries[i] = AV_RB32(table->entries + i); + + av_log(s, AV_LOG_TRACE, "Table, size = %u, offset = %u\n", table->count, table->offset); + for (size_t i = 0; i < table->count; i++) + av_log(s, AV_LOG_TRACE, " [%02zu]: %u\n", i, table->entries[i]); + + return 0; +} + +static int scd_read_offsets(AVFormatContext *s) +{ + int64_t ret; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_OFFSET_HEADER_SIZE]; + + if ((ret = avio_read(s->pb, buf, SCD_OFFSET_HEADER_SIZE)) < 0) + return ret; + + ctx->hdr.table0.count = AV_RB16(buf + 0); + ctx->hdr.table1.count = AV_RB16(buf + 2); + ctx->hdr.table2.count = AV_RB16(buf + 4); + ctx->hdr.unk2 = AV_RB16(buf + 6); + ctx->hdr.table0.offset = AV_RB32(buf + 8); + ctx->hdr.table1.offset = AV_RB32(buf + 12); + ctx->hdr.table2.offset = AV_RB32(buf + 16); + ctx->hdr.unk3 = AV_RB32(buf + 20); + ctx->hdr.unk4 = AV_RB32(buf + 24); + + if ((ret = scd_read_table(s, &ctx->hdr.table0)) < 0) + return ret; + + if ((ret = scd_read_table(s, &ctx->hdr.table1)) < 0) + return ret; + + if ((ret = scd_read_table(s, &ctx->hdr.table2)) < 0) + return ret; + + return 0; +} + +static int scd_read_track(AVFormatContext *s, SCDTrackHeader *track, int index) +{ + int64_t ret; + uint32_t hoffset; + AVStream *st; + AVCodecParameters *par; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_TRACK_HEADER_SIZE]; + + /* Mark as experimental until I find more files from more than just one game. */ + if (s->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) { + av_log(s, AV_LOG_ERROR, "SCD demuxing is experimental, " + "add '-strict %d' if you want to use it.\n", + FF_COMPLIANCE_EXPERIMENTAL); + return AVERROR_EXPERIMENTAL; + } + + hoffset = ctx->hdr.table1.entries[index]; + + if ((ret = avio_seek(s->pb, hoffset, SEEK_SET)) < 0) + return ret; + + if ((ret = avio_read(s->pb, buf, SCD_TRACK_HEADER_SIZE)) < 0) + return ret; + + track->length = AV_RB32(buf + 0); + track->num_channels = AV_RB32(buf + 4); + track->sample_rate = AV_RB32(buf + 8); + track->data_type = AV_RB32(buf + 12); + track->loop_start = AV_RB32(buf + 16); + track->loop_end = AV_RB32(buf + 20); + track->data_offset = AV_RB32(buf + 24); + track->aux_count = AV_RB32(buf + 28); + + /* Sanity checks */ + if (track->num_channels > 8 || track->sample_rate >= 192000 || + track->loop_start > track->loop_end) + return AVERROR_INVALIDDATA; + + track->absolute_offset = hoffset + SCD_TRACK_HEADER_SIZE + track->data_offset; + track->bytes_read = 0; + + /* Not sure what to do with these, it seems to be fine to ignore them. */ + if (track->aux_count != 0) + av_log(s, AV_LOG_DEBUG, "[%d] Track has %u auxillary chunk(s).\n", index, track->aux_count); + + if ((st = avformat_new_stream(s, NULL)) == NULL) + return AVERROR(ENOMEM); + + par = st->codecpar; + par->codec_type = AVMEDIA_TYPE_AUDIO; + par->channels = (int)track->num_channels; + par->sample_rate = (int)track->sample_rate; + st->index = index; + st->start_time = 0; + + /* TODO: Check this with other types. Drakengard 3 MP3s have 47999 instead of 48000. */ + if (track->data_type == SCD_TRACK_ID_MP3) + par->sample_rate += 1; + + avpriv_set_pts_info(st, 64, 1, par->sample_rate); + + if (av_dict_set_int(&st->metadata, "start", track->absolute_offset, 0) < 0) + return AVERROR(ENOMEM); + + if (av_dict_set_int(&st->metadata, "loop_start", track->loop_start, 0) < 0) + return AVERROR(ENOMEM); + + if (av_dict_set_int(&st->metadata, "loop_end", track->loop_end, 0) < 0) + return AVERROR(ENOMEM); + + switch(track->data_type) { + 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; + break; + case SCD_TRACK_ID_MP3: + par->codec_id = AV_CODEC_ID_MP3; + ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW; + break; + case SCD_TRACK_ID_OGG: + case SCD_TRACK_ID_MS_ADPCM: + default: + par->codec_id = AV_CODEC_ID_NONE; + avpriv_request_sample(s, "data type %u", track->data_type); + } + + return 0; +} + +static int scd_read_header(AVFormatContext *s) +{ + int64_t ret; + SCDDemuxContext *ctx = s->priv_data; + uint8_t buf[SCD_MIN_HEADER_SIZE]; + + if ((ret = avio_read(s->pb, buf, SCD_MIN_HEADER_SIZE)) < 0) + return ret; + + ctx->hdr.magic = AV_RB64(buf + 0); + ctx->hdr.version = AV_RB32(buf + 8); + ctx->hdr.unk1 = AV_RB16(buf + 12); + ctx->hdr.header_size = AV_RB16(buf + 14); + ctx->hdr.file_size = AV_RB32(buf + 16); + + if (ctx->hdr.magic != SCD_MAGIC) + return AVERROR_INVALIDDATA; + + if (ctx->hdr.version != 3) { + avpriv_request_sample(s, "SCD version %u", ctx->hdr.version); + return AVERROR_PATCHWELCOME; + } + + if (ctx->hdr.header_size < SCD_MIN_HEADER_SIZE) + return AVERROR_INVALIDDATA; + + if ((ret = avio_skip(s->pb, ctx->hdr.header_size - SCD_MIN_HEADER_SIZE)) < 0) + return ret; + + if ((ret = scd_read_offsets(s)) < 0) + return ret; + + ctx->tracks = av_calloc(ctx->hdr.table1.count, sizeof(SCDTrackHeader)); + if (ctx->tracks == NULL) + return AVERROR(ENOMEM); + + for (int i = 0; i < ctx->hdr.table1.count; i++) { + if ((ret = scd_read_track(s, ctx->tracks + i, i)) < 0) + return ret; + } + + if (ctx->hdr.table1.count == 0) + return 0; + + if ((ret = avio_seek(s->pb, ctx->tracks[0].absolute_offset, SEEK_SET)) < 0) + return ret; + + return 0; +} + +static int scd_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + SCDDemuxContext *ctx = s->priv_data; + AVCodecParameters *par; + + /* Streams aren't interleaved, round-robin them. */ + for (int i = 0; i < ctx->hdr.table1.count; i++) { + int64_t ret; + int size; + SCDTrackHeader *trk; + + ctx->current_track %= ctx->hdr.table1.count; + + trk = ctx->tracks + ctx->current_track; + par = s->streams[ctx->current_track]->codecpar; + + if (trk->bytes_read >= trk->length) + continue; + + if ((ret = avio_seek(s->pb, trk->absolute_offset + trk->bytes_read, SEEK_SET)) < 0) + return ret; + + switch(trk->data_type) { + case SCD_TRACK_ID_PCM: + size = par->block_align; + break; + case SCD_TRACK_ID_MP3: + default: + size = FFMIN(trk->length - trk->bytes_read, 4096); + break; + } + + ret = av_get_packet(s->pb, pkt, size); + if (ret == AVERROR_EOF) { + trk->length = trk->bytes_read; + continue; + } else if (ret < 0) { + return ret; + } + + 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)); + } + + trk->bytes_read += ret; + pkt->flags &= ~AV_PKT_FLAG_CORRUPT; + pkt->stream_index = ctx->current_track; + + ctx->current_track++; + return 0; + } + + return AVERROR_EOF; +} + +static int scd_seek(AVFormatContext *s, int stream_index, + int64_t pts, int flags) +{ + SCDDemuxContext *ctx = s->priv_data; + + if (pts != 0) + return AVERROR(EINVAL); + + for(int i = 0; i < ctx->hdr.table1.count; ++i) + ctx->tracks[i].bytes_read = 0; + + return 0; +} + +static int scd_read_close(AVFormatContext *s) +{ + SCDDemuxContext *ctx = s->priv_data; + + av_freep(&ctx->hdr.table0.entries); + av_freep(&ctx->hdr.table1.entries); + av_freep(&ctx->hdr.table2.entries); + av_freep(&ctx->tracks); + return 0; +} + +const AVInputFormat ff_scd_demuxer = { + .name = "scd", + .long_name = NULL_IF_CONFIG_SMALL("Square Enix SCD"), + .priv_data_size = sizeof(SCDDemuxContext), + .flags_internal = FF_FMT_INIT_CLEANUP, + .read_probe = scd_probe, + .read_header = scd_read_header, + .read_packet = scd_read_packet, + .read_seek = scd_seek, + .read_close = scd_read_close, +}; diff --git a/libavformat/sdp.c b/libavformat/sdp.c index 1200e553f9..d63a0b34c4 100644 --- a/libavformat/sdp.c +++ b/libavformat/sdp.c @@ -151,7 +151,8 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url) } #define MAX_PSET_SIZE 1024 -static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) +static int extradata2psets(AVFormatContext *s, const AVCodecParameters *par, + char **out) { char *psets, *p; const uint8_t *r; @@ -162,15 +163,18 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) uint8_t *tmpbuf = NULL; const uint8_t *sps = NULL, *sps_end; + *out = NULL; + if (par->extradata_size > MAX_EXTRADATA_SIZE) { av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); - - return NULL; + return AVERROR_INVALIDDATA; } if (par->extradata[0] == 1) { - if (ff_avc_write_annexb_extradata(par->extradata, &extradata, - &extradata_size)) - return NULL; + int ret = ff_avc_write_annexb_extradata(par->extradata, &extradata, + &extradata_size); + if (ret < 0) + return ret; + tmpbuf = extradata; } @@ -178,7 +182,7 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) if (!psets) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n"); av_free(tmpbuf); - return NULL; + return AVERROR(ENOMEM); } memcpy(psets, pset_string, strlen(pset_string)); p = psets + strlen(pset_string); @@ -203,11 +207,12 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) sps_end = r1; } if (!av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r)) { - av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", MAX_PSET_SIZE - (p - psets), r1 - r); + av_log(s, AV_LOG_ERROR, "Cannot Base64-encode %"PTRDIFF_SPECIFIER" %"PTRDIFF_SPECIFIER"!\n", + MAX_PSET_SIZE - (p - psets), r1 - r); av_free(psets); av_free(tmpbuf); - return NULL; + return AVERROR_INVALIDDATA; } p += strlen(p); r = r1; @@ -216,14 +221,14 @@ static char *extradata2psets(AVFormatContext *s, AVCodecParameters *par) memcpy(p, profile_string, strlen(profile_string)); p += strlen(p); ff_data_to_hex(p, sps + 1, 3, 0); - p[6] = '\0'; } av_free(tmpbuf); - return psets; + *out = psets; + return 0; } -static char *extradata2psets_hevc(AVCodecParameters *par) +static int extradata2psets_hevc(const AVCodecParameters *par, char **out) { char *psets; uint8_t *extradata = par->extradata; @@ -232,7 +237,9 @@ static char *extradata2psets_hevc(AVCodecParameters *par) int ps_pos[3] = { 0 }; static const char * const ps_names[3] = { "vps", "sps", "pps" }; int num_arrays, num_nalus; - int pos, i, j; + int pos, i, j, ret = 0; + + *out = NULL; // Convert to hvcc format. Since we need to group multiple NALUs of // the same type, and we might need to convert from one format to the @@ -240,9 +247,13 @@ static char *extradata2psets_hevc(AVCodecParameters *par) // format. if (par->extradata[0] != 1) { AVIOContext *pb; - if (avio_open_dyn_buf(&pb) < 0) - return NULL; - if (ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0) < 0) { + + ret = avio_open_dyn_buf(&pb); + if (ret < 0) + return ret; + + ret = ff_isom_write_hvcc(pb, par->extradata, par->extradata_size, 0); + if (ret < 0) { avio_close_dyn_buf(pb, &tmpbuf); goto err; } @@ -285,8 +296,11 @@ static char *extradata2psets_hevc(AVCodecParameters *par) goto err; psets = av_mallocz(MAX_PSET_SIZE); - if (!psets) + if (!psets) { + ret = AVERROR(ENOMEM); goto err; + } + psets[0] = '\0'; for (i = 0; i < 3; i++) { @@ -317,41 +331,48 @@ static char *extradata2psets_hevc(AVCodecParameters *par) } av_free(tmpbuf); - return psets; - + *out = psets; + return 0; err: + if (ret >= 0) + ret = AVERROR_INVALIDDATA; av_free(tmpbuf); - return NULL; + return ret; } -static char *extradata2config(AVFormatContext *s, AVCodecParameters *par) +static int extradata2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { char *config; + *out = NULL; + if (par->extradata_size > MAX_EXTRADATA_SIZE) { av_log(s, AV_LOG_ERROR, "Too much extradata!\n"); - - return NULL; + return AVERROR_INVALIDDATA; } config = av_malloc(10 + par->extradata_size * 2); if (!config) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); - return NULL; + return AVERROR(ENOMEM); } memcpy(config, "; config=", 9); ff_data_to_hex(config + 9, par->extradata, par->extradata_size, 0); - config[9 + par->extradata_size * 2] = 0; - return config; + *out = config; + return 0; } -static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par) +static int xiph_extradata2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { uint8_t *config; char *encoded_config; const uint8_t *header_start[3]; int headers_len, header_len[3], config_len; - int first_header_size; + int first_header_size, ret; + + *out = NULL; switch (par->codec_id) { case AV_CODEC_ID_THEORA: @@ -362,14 +383,15 @@ static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par) break; default: av_log(s, AV_LOG_ERROR, "Unsupported Xiph codec ID\n"); - return NULL; + return AVERROR(ENOSYS); } - if (avpriv_split_xiph_headers(par->extradata, par->extradata_size, - first_header_size, header_start, - header_len) < 0) { + ret = avpriv_split_xiph_headers(par->extradata, par->extradata_size, + first_header_size, header_start, + header_len); + if (ret < 0) { av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); - return NULL; + return ret; } headers_len = header_len[0] + header_len[2]; @@ -407,15 +429,16 @@ static char *xiph_extradata2config(AVFormatContext *s, AVCodecParameters *par) config, config_len); av_free(config); - return encoded_config; + *out = encoded_config; + return 0; xiph_fail: av_log(s, AV_LOG_ERROR, "Not enough memory for configuration string\n"); - return NULL; + return AVERROR(ENOMEM); } -static int latm_context2profilelevel(AVCodecParameters *par) +static int latm_context2profilelevel(const AVCodecParameters *par) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -444,7 +467,8 @@ static int latm_context2profilelevel(AVCodecParameters *par) return profile_level; } -static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) +static int latm_context2config(AVFormatContext *s, const AVCodecParameters *par, + char **out) { /* MP4A-LATM * The RTP payload format specification is described in RFC 3016 @@ -454,12 +478,14 @@ static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) int rate_index; char *config; + *out = NULL; + for (rate_index = 0; rate_index < 16; rate_index++) - if (avpriv_mpeg4audio_sample_rates[rate_index] == par->sample_rate) + if (ff_mpeg4audio_sample_rates[rate_index] == par->sample_rate) break; if (rate_index == 16) { av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return NULL; + return AVERROR(ENOSYS); } config_byte[0] = 0x40; @@ -472,268 +498,319 @@ static char *latm_context2config(AVFormatContext *s, AVCodecParameters *par) config = av_malloc(6*2+1); if (!config) { av_log(s, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n"); - return NULL; + return AVERROR(ENOMEM); } ff_data_to_hex(config, config_byte, 6, 1); - config[12] = 0; - return config; + *out = config; + return 0; } -static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int payload_type, AVFormatContext *fmt) +static int sdp_write_media_attributes(char *buff, int size, const AVStream *st, + int payload_type, AVFormatContext *fmt) { char *config = NULL; - AVCodecParameters *p = st->codecpar; + const AVCodecParameters *p = st->codecpar; + int ret = 0; switch (p->codec_id) { - case AV_CODEC_ID_DIRAC: - av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type); - break; - case AV_CODEC_ID_H264: { - int mode = 1; - if (fmt && fmt->oformat && fmt->oformat->priv_class && - av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) - mode = 0; - if (p->extradata_size) { - config = extradata2psets(fmt, p); - } - av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" - "a=fmtp:%d packetization-mode=%d%s\r\n", - payload_type, - payload_type, mode, config ? config : ""); - break; + case AV_CODEC_ID_DIRAC: + av_strlcatf(buff, size, "a=rtpmap:%d VC2/90000\r\n", payload_type); + break; + case AV_CODEC_ID_H264: { + int mode = 1; + if (fmt && fmt->oformat && fmt->oformat->priv_class && + av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0")) + mode = 0; + if (p->extradata_size) { + ret = extradata2psets(fmt, p, &config); + if (ret < 0) + return ret; } - case AV_CODEC_ID_H261: - { - const char *pic_fmt = NULL; - /* only QCIF and CIF are specified as supported in RFC 4587 */ - if (p->width == 176 && p->height == 144) - pic_fmt = "QCIF=1"; - else if (p->width == 352 && p->height == 288) - pic_fmt = "CIF=1"; - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); - if (pic_fmt) - av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); - break; + av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n" + "a=fmtp:%d packetization-mode=%d%s\r\n", + payload_type, + payload_type, mode, config ? config : ""); + break; + } + case AV_CODEC_ID_H261: + { + const char *pic_fmt = NULL; + /* only QCIF and CIF are specified as supported in RFC 4587 */ + if (p->width == 176 && p->height == 144) + pic_fmt = "QCIF=1"; + else if (p->width == 352 && p->height == 288) + pic_fmt = "CIF=1"; + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d H261/90000\r\n", payload_type); + if (pic_fmt) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", payload_type, pic_fmt); + break; + } + case AV_CODEC_ID_H263: + case AV_CODEC_ID_H263P: + /* a=framesize is required by 3GPP TS 26.234 (PSS). It + * actually specifies the maximum video size, but we only know + * the current size. This is required for playback on Android + * stagefright and on Samsung bada. */ + if (!fmt || !fmt->oformat->priv_class || + !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || + p->codec_id == AV_CODEC_ID_H263P) + av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" + "a=framesize:%d %d-%d\r\n", + payload_type, + payload_type, p->width, p->height); + break; + case AV_CODEC_ID_HEVC: + if (p->extradata_size) { + ret = extradata2psets_hevc(p, &config); + if (ret < 0) + return ret; } - case AV_CODEC_ID_H263: - case AV_CODEC_ID_H263P: - /* a=framesize is required by 3GPP TS 26.234 (PSS). It - * actually specifies the maximum video size, but we only know - * the current size. This is required for playback on Android - * stagefright and on Samsung bada. */ - if (!fmt || !fmt->oformat->priv_class || - !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") || - p->codec_id == AV_CODEC_ID_H263P) - av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n" - "a=framesize:%d %d-%d\r\n", - payload_type, - payload_type, p->width, p->height); - break; - case AV_CODEC_ID_HEVC: - if (p->extradata_size) - config = extradata2psets_hevc(p); - av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); - if (config) - av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", - payload_type, config); - break; - case AV_CODEC_ID_MPEG4: + av_strlcatf(buff, size, "a=rtpmap:%d H265/90000\r\n", payload_type); + if (config) + av_strlcatf(buff, size, "a=fmtp:%d %s\r\n", + payload_type, config); + break; + case AV_CODEC_ID_MPEG4: + if (p->extradata_size) { + ret = extradata2config(fmt, p, &config); + if (ret < 0) + return ret; + } + av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" + "a=fmtp:%d profile-level-id=1%s\r\n", + payload_type, + payload_type, config ? config : ""); + break; + case AV_CODEC_ID_AAC: + if (fmt && fmt->oformat && fmt->oformat->priv_class && + av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { + ret = latm_context2config(fmt, p, &config); + if (ret < 0) + 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, latm_context2profilelevel(p), config); + } else { if (p->extradata_size) { - config = extradata2config(fmt, p); - } - av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n" - "a=fmtp:%d profile-level-id=1%s\r\n", - payload_type, - payload_type, config ? config : ""); - break; - case AV_CODEC_ID_AAC: - if (fmt && fmt->oformat && fmt->oformat->priv_class && - av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) { - config = latm_context2config(fmt, p); - if (!config) - return NULL; - 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, latm_context2profilelevel(p), config); + ret = extradata2config(fmt, p, &config); + if (ret < 0) + return ret; } else { - if (p->extradata_size) { - config = extradata2config(fmt, p); - } else { - /* FIXME: maybe we can forge config information based on the - * codec parameters... - */ - av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); - return NULL; - } - if (!config) { - return NULL; - } - av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" - "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, config); + /* FIXME: maybe we can forge config information based on the + * codec parameters... + */ + av_log(fmt, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n"); + return AVERROR(ENOSYS); } - break; - case AV_CODEC_ID_PCM_S16BE: - 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); - break; - case AV_CODEC_ID_PCM_S24BE: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", - payload_type, - p->sample_rate, p->channels); - break; - case AV_CODEC_ID_PCM_MULAW: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", - payload_type, - p->sample_rate, p->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); - 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", + av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n" + "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); - 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); - break; - case AV_CODEC_ID_VORBIS: - if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else - av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); - if (!config) - return NULL; - - 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, config); - break; - case AV_CODEC_ID_THEORA: { - const char *pix_fmt; - switch (p->format) { - case AV_PIX_FMT_YUV420P: - pix_fmt = "YCbCr-4:2:0"; - break; - case AV_PIX_FMT_YUV422P: - pix_fmt = "YCbCr-4:2:2"; - break; - case AV_PIX_FMT_YUV444P: - pix_fmt = "YCbCr-4:4:4"; - break; - default: - av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); - return NULL; - } - - if (p->extradata_size) - config = xiph_extradata2config(fmt, p); - else - av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); - if (!config) - return NULL; - - av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" - "a=fmtp:%d delivery-method=inline; " - "width=%d; height=%d; sampling=%s; " - "configuration=%s\r\n", - payload_type, payload_type, - p->width, p->height, pix_fmt, config); - break; + payload_type, config); } - case AV_CODEC_ID_VP8: - av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", - payload_type); - break; - case AV_CODEC_ID_VP9: - av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n", - payload_type); - break; - case AV_CODEC_ID_MJPEG: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", - payload_type); - break; - case AV_CODEC_ID_ADPCM_G722: - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", - payload_type, - 8000, p->channels); - break; - case AV_CODEC_ID_ADPCM_G726: { - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d AAL2-G726-%d/%d\r\n", - payload_type, - p->bits_per_coded_sample*8, - p->sample_rate); - break; + break; + case AV_CODEC_ID_PCM_S16BE: + 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); + break; + case AV_CODEC_ID_PCM_S24BE: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d L24/%d/%d\r\n", + payload_type, + p->sample_rate, p->channels); + break; + case AV_CODEC_ID_PCM_MULAW: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n", + payload_type, + p->sample_rate, p->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); + 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); + 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); + break; + case AV_CODEC_ID_VORBIS: + if (p->extradata_size) + ret = xiph_extradata2config(fmt, p, &config); + else { + av_log(fmt, AV_LOG_ERROR, "Vorbis configuration info missing\n"); + ret = AVERROR_INVALIDDATA; } - case AV_CODEC_ID_ADPCM_G726LE: { - if (payload_type >= RTP_PT_PRIVATE) - av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", - payload_type, - p->bits_per_coded_sample*8, - p->sample_rate); + if (ret < 0) + return ret; + + 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, config); + break; + case AV_CODEC_ID_THEORA: { + const char *pix_fmt; + switch (p->format) { + case AV_PIX_FMT_YUV420P: + pix_fmt = "YCbCr-4:2:0"; break; - } - case AV_CODEC_ID_ILBC: - av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" - "a=fmtp:%d mode=%d\r\n", - payload_type, p->sample_rate, - payload_type, p->block_align == 38 ? 20 : 30); + case AV_PIX_FMT_YUV422P: + pix_fmt = "YCbCr-4:2:2"; break; - case AV_CODEC_ID_SPEEX: - av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", - payload_type, p->sample_rate); - break; - case AV_CODEC_ID_OPUS: - /* The opus RTP draft says that all opus streams MUST be declared - as stereo, to avoid negotiation failures. The actual number of - channels can change on a packet-by-packet basis. The number of - channels a receiver prefers to receive or a sender plans to send - can be declared via fmtp parameters (both default to mono), but - 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) { - av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", - payload_type); - } + case AV_PIX_FMT_YUV444P: + pix_fmt = "YCbCr-4:4:4"; break; default: - /* Nothing special to do here... */ + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return AVERROR(ENOSYS); + } + + if (p->extradata_size) + ret = xiph_extradata2config(fmt, p, &config); + else { + av_log(fmt, AV_LOG_ERROR, "Theora configuration info missing\n"); + ret = AVERROR_INVALIDDATA; + } + if (ret < 0) + return ret; + + av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n" + "a=fmtp:%d delivery-method=inline; " + "width=%d; height=%d; sampling=%s; " + "configuration=%s\r\n", + payload_type, payload_type, + p->width, p->height, pix_fmt, config); + break; + } + case AV_CODEC_ID_BITPACKED: + case AV_CODEC_ID_RAWVIDEO: { + const char *pix_fmt; + int bit_depth = 8; + + switch (p->format) { + case AV_PIX_FMT_UYVY422: + pix_fmt = "YCbCr-4:2:2"; break; + case AV_PIX_FMT_YUV422P10: + pix_fmt = "YCbCr-4:2:2"; + bit_depth = 10; + break; + case AV_PIX_FMT_YUV420P: + pix_fmt = "YCbCr-4:2:0"; + break; + case AV_PIX_FMT_RGB24: + pix_fmt = "RGB"; + break; + case AV_PIX_FMT_BGR24: + pix_fmt = "BGR"; + break; + default: + av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n"); + return AVERROR(ENOSYS); + } + + av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n" + "a=fmtp:%d sampling=%s; " + "width=%d; height=%d; " + "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; + } + + case AV_CODEC_ID_VP8: + av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_VP9: + av_strlcatf(buff, size, "a=rtpmap:%d VP9/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_MJPEG: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n", + payload_type); + break; + case AV_CODEC_ID_ADPCM_G722: + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n", + payload_type, + 8000, p->channels); + break; + case AV_CODEC_ID_ADPCM_G726: { + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d AAL2-G726-%d/%d\r\n", + payload_type, + p->bits_per_coded_sample*8, + p->sample_rate); + break; + } + case AV_CODEC_ID_ADPCM_G726LE: { + if (payload_type >= RTP_PT_PRIVATE) + av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n", + payload_type, + p->bits_per_coded_sample*8, + p->sample_rate); + break; + } + case AV_CODEC_ID_ILBC: + av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n" + "a=fmtp:%d mode=%d\r\n", + payload_type, p->sample_rate, + payload_type, p->block_align == 38 ? 20 : 30); + break; + case AV_CODEC_ID_SPEEX: + av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n", + payload_type, p->sample_rate); + break; + case AV_CODEC_ID_OPUS: + /* The opus RTP draft says that all opus streams MUST be declared + as stereo, to avoid negotiation failures. The actual number of + channels can change on a packet-by-packet basis. The number of + channels a receiver prefers to receive or a sender plans to send + can be declared via fmtp parameters (both default to mono), but + 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) { + av_strlcatf(buff, size, "a=fmtp:%d sprop-stereo=1\r\n", + payload_type); + } + break; + default: + /* Nothing special to do here... */ + break; } av_free(config); - return buff; + return 0; } -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt) +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) { - AVCodecParameters *p = st->codecpar; + const AVCodecParameters *p = st->codecpar; const char *type; int payload_type; @@ -752,7 +829,7 @@ void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, av_strlcatf(buff, size, "b=AS:%"PRId64"\r\n", p->bit_rate / 1000); } - sdp_write_media_attributes(buff, size, st, payload_type, fmt); + return sdp_write_media_attributes(buff, size, st, payload_type, fmt); } int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) @@ -798,10 +875,13 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) ttl = 0; } for (j = 0; j < ac[i]->nb_streams; j++) { - ff_sdp_write_media(buf, size, ac[i]->streams[j], index++, - dst[0] ? dst : NULL, dst_type, - (port > 0) ? port + j * 2 : 0, - ttl, ac[i]); + int ret = ff_sdp_write_media(buf, size, ac[i]->streams[j], index++, + dst[0] ? dst : NULL, dst_type, + (port > 0) ? port + j * 2 : 0, + ttl, ac[i]); + if (ret < 0) + return ret; + if (port <= 0) { av_strlcatf(buf, size, "a=control:streamid=%d\r\n", i + j); @@ -830,9 +910,10 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size) return AVERROR(ENOSYS); } -void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx, - const char *dest_addr, const char *dest_type, - int port, int ttl, AVFormatContext *fmt) +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) { + return AVERROR(ENOSYS); } #endif diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index ff8cb66aca..737805faa6 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -170,54 +170,13 @@ static int film_init(AVFormatContext *format_context) static int write_header(AVFormatContext *format_context, uint8_t *header, unsigned header_size) { - int ret = 0; - 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(header_size); - if (!buf) - return AVERROR(ENOMEM); - read_buf[0] = buf; - read_buf[1] = header; - read_size[1] = header_size; - - /* Write the header at the beginning of the file, shifting all content as necessary; - * based on the approach used by MOV faststart. */ - avio_flush(format_context->pb); - ret = format_context->io_open(format_context, &read_pb, format_context->url, AVIO_FLAG_READ, NULL); - if (ret < 0) { - av_log(format_context, AV_LOG_ERROR, "Unable to re-open %s output file to " - "write the header\n", format_context->url); - av_free(buf); + int ret = ff_format_shift_data(format_context, 0, header_size); + if (ret < 0) return ret; - } - /* Mark the end of the shift to up to the last data we are going to write, - * and get ready for writing */ - pos_end = avio_tell(format_context->pb) + header_size; - pos = avio_seek(format_context->pb, 0, SEEK_SET); + avio_seek(format_context->pb, 0, SEEK_SET); + avio_write(format_context->pb, header, header_size); - /* start reading at where the new header will be placed */ - avio_seek(read_pb, 0, SEEK_SET); - - /* shift data by chunk of at most header_size */ - do { - int n; - read_size[read_buf_id] = avio_read(read_pb, read_buf[read_buf_id], - header_size); - read_buf_id ^= 1; - n = read_size[read_buf_id]; - if (n <= 0) - break; - avio_write(format_context->pb, read_buf[read_buf_id], n); - pos += n; - } while (pos < pos_end); - ff_format_io_close(format_context, &read_pb); - - av_free(buf); return 0; } diff --git a/libavformat/segment.c b/libavformat/segment.c index 2b024fd373..e9b0aa4fa8 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -158,6 +158,7 @@ static int segment_mux_init(AVFormatContext *s) av_dict_copy(&oc->metadata, s->metadata, 0); oc->opaque = s->opaque; oc->io_close = s->io_close; + oc->io_close2 = s->io_close2; oc->io_open = s->io_open; oc->flags = s->flags; @@ -569,7 +570,7 @@ static int open_null_ctx(AVIOContext **ctx) uint8_t *buf = av_malloc(buf_size); if (!buf) return AVERROR(ENOMEM); - *ctx = avio_alloc_context(buf, buf_size, AVIO_FLAG_WRITE, NULL, NULL, NULL, NULL); + *ctx = avio_alloc_context(buf, buf_size, 1, NULL, NULL, NULL, NULL); if (!*ctx) { av_free(buf); return AVERROR(ENOMEM); @@ -984,15 +985,17 @@ static int seg_write_trailer(struct AVFormatContext *s) return ret; } -static int seg_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) +static int seg_check_bitstream(AVFormatContext *s, AVStream *st, + const AVPacket *pkt) { SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; if (oc->oformat->check_bitstream) { - int ret = oc->oformat->check_bitstream(oc, pkt); + AVStream *const ost = oc->streams[st->index]; + int ret = oc->oformat->check_bitstream(oc, ost, pkt); if (ret == 1) { - FFStream *const sti = ffstream( s->streams[pkt->stream_index]); - FFStream *const osti = ffstream(oc->streams[pkt->stream_index]); + FFStream *const sti = ffstream(st); + FFStream *const osti = ffstream(ost); sti->bsfc = osti->bsfc; osti->bsfc = NULL; } diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c index 27b59c299c..a0ea5b8fa8 100644 --- a/libavformat/smoothstreamingenc.c +++ b/libavformat/smoothstreamingenc.c @@ -40,17 +40,15 @@ #include "libavutil/intreadwrite.h" typedef struct Fragment { - char file[1024]; - char infofile[1024]; int64_t start_time, duration; int n; int64_t start_pos, size; + char file[1024]; + char infofile[1024]; } Fragment; typedef struct OutputStream { AVFormatContext *ctx; - char dirname[1024]; - uint8_t iobuf[32768]; URLContext *out; // Current output stream where all output is written URLContext *out2; // Auxiliary output stream where all output is also written URLContext *tail_out; // The actual main output stream, if we're currently seeked back to write elsewhere @@ -64,6 +62,8 @@ typedef struct OutputStream { char *private_str; int packet_size; int audio_tag; + char dirname[1024]; + uint8_t iobuf[32768]; } OutputStream; typedef struct SmoothStreamingContext { @@ -335,7 +335,7 @@ static int ism_write_header(AVFormatContext *s) st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio; st->time_base = s->streams[i]->time_base; - ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), AVIO_FLAG_WRITE, os, NULL, ism_write, ism_seek); + ctx->pb = avio_alloc_context(os->iobuf, sizeof(os->iobuf), 1, os, NULL, ism_write, ism_seek); if (!ctx->pb) { return AVERROR(ENOMEM); } diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c index e8f54bff4b..3be89328df 100644 --- a/libavformat/spdifenc.c +++ b/libavformat/spdifenc.c @@ -263,7 +263,7 @@ static int spdif_header_dts(AVFormatContext *s, AVPacket *pkt) case DCA_SYNCWORD_CORE_BE: blocks = (AV_RB16(pkt->data + 4) >> 2) & 0x7f; core_size = ((AV_RB24(pkt->data + 5) >> 4) & 0x3fff) + 1; - sample_rate = avpriv_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; + sample_rate = ff_dca_sample_rates[(pkt->data[8] >> 2) & 0x0f]; break; case DCA_SYNCWORD_CORE_LE: blocks = (AV_RL16(pkt->data + 4) >> 2) & 0x7f; diff --git a/libavformat/takdec.c b/libavformat/takdec.c index 839e3cc781..cc1f049512 100644 --- a/libavformat/takdec.c +++ b/libavformat/takdec.c @@ -109,7 +109,7 @@ static int tak_read_header(AVFormatContext *s) break; case TAK_METADATA_MD5: { uint8_t md5[16]; - int i; + char md5_hex[2 * sizeof(md5) + 1]; if (size != 19) return AVERROR_INVALIDDATA; @@ -121,10 +121,8 @@ static int tak_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } - av_log(s, AV_LOG_VERBOSE, "MD5="); - for (i = 0; i < 16; i++) - av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]); - av_log(s, AV_LOG_VERBOSE, "\n"); + ff_data_to_hex(md5_hex, md5, sizeof(md5), 1); + av_log(s, AV_LOG_VERBOSE, "MD5=%s\n", md5_hex); break; } case TAK_METADATA_END: { @@ -173,9 +171,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/tee.c b/libavformat/tee.c index dfdf70cb08..b3bcd70b9f 100644 --- a/libavformat/tee.c +++ b/libavformat/tee.c @@ -237,6 +237,7 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) avf2->opaque = avf->opaque; avf2->io_open = avf->io_open; avf2->io_close = avf->io_close; + avf2->io_close2 = avf->io_close2; avf2->interrupt_callback = avf->interrupt_callback; avf2->flags = avf->flags; avf2->strict_std_compliance = avf->strict_std_compliance; diff --git a/libavformat/tests/imf.c b/libavformat/tests/imf.c new file mode 100644 index 0000000000..142aa04261 --- /dev/null +++ b/libavformat/tests/imf.c @@ -0,0 +1,526 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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) Sandflow Consulting LLC + * + * 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 OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * Tests for IMF CPL and ASSETMAP processing + * + * @author Valentin Noel + * @author Pierre-Anthony Lemieux + * @file + * @ingroup lavu_imf + */ + +#include "libavformat/imf_cpl.c" +#include "libavformat/imfdec.c" +#include "libavformat/mxf.h" + +#include + +const char *cpl_doc = + "" + "urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5" + "2021-07-13T17:06:22Z" + "FFMPEG" + "FFMPEG sample content" + "" + " " + " urn:uuid:8e097bb0-cff7-4969-a692-bad47bfb528f" + " " + "" + "24000 1001" + "" + "" + "urn:uuid:81fed4e5-9722-400a-b9d1-7f2bd21df4b6" + "" + "" + "urn:uuid:16327185-9205-47ef-a17b-ee28df251db7" + "urn:uuid:461f5424-8f6e-48a9-a385-5eda46fda381" + "" + "" + "urn:uuid:ea3d0f23-55d6-4e03-86ec-cfe0666f0e6a" + "24" + "" + "" + "5" + "" + "" + "" + "" + "" + "urn:uuid:6ae100b0-92d1-41be-9321-85e0933dfc42" + "urn:uuid:e8ef9653-565c-479c-8039-82d4547973c5" + "" + "" + "urn:uuid:7d418acb-07a3-4e57-984c-b8ea2f7de4ec" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:6f768ca4-c89e-4dac-9056-a29425d40ba1" + "" + "" + "" + "" + "urn:uuid:754dae53-c25f-4f3c-97e4-2bfe5463f83b" + "urn:uuid:68e3fae5-d94b-44d2-92a6-b94877fbcdb5" + "" + "" + "urn:uuid:61ce2a70-10a2-4521-850b-4218755ff3c9" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488" + "" + "" + "" + "" + "urn:uuid:d29b3884-6633-4dad-9c67-7154af342bc6" + "urn:uuid:6978c106-95bc-424b-a17c-628206a5892d" + "" + "" + "urn:uuid:001ea472-f5da-436c-86de-acaa68c1a7e4" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488" + "" + "" + "" + "" + "urn:uuid:02af22bf-f776-488a-b001-eb6e16953119" + "urn:uuid:19ff6da1-be79-4235-8d04-42201ad06e65" + "" + "" + "urn:uuid:dfa84292-0609-4097-824c-8e2e15e2ce4d" + "24" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:bd6272b6-511e-47c1-93bc-d56ebd314a70" + "" + "" + "" + "" + "" + "" + "urn:uuid:a94be493-cd55-4bf7-b496-ea87bfe38632" + "" + "" + "urn:uuid:20c6020b-1fc0-4080-bcf7-89f09f95bea8" + "urn:uuid:461f5424-8f6e-48a9-a385-5eda46fda381" + "" + "" + "urn:uuid:d1f93845-d3e5-4c3b-aa67-8d96c45cfe9c" + "36" + "" + "" + "20" + "" + "" + "" + "24" + "" + "" + "" + "" + "" + "urn:uuid:9b509f42-e4e8-4f78-8c2a-12ddd79ef3c5" + "urn:uuid:e8ef9653-565c-479c-8039-82d4547973c5" + "" + "" + "urn:uuid:a733d812-a3d7-45e9-ba50-13b856d5d35a" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:f3b263b3-096b-4360-a952-b1a9623cd0ca" + "" + "" + "" + "" + "urn:uuid:19a282e6-beac-4d99-a008-afa61378eb6c" + "urn:uuid:68e3fae5-d94b-44d2-92a6-b94877fbcdb5" + "" + "" + "urn:uuid:53de5ff9-f5f7-47c5-a2d8-117c36cce517" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535" + "" + "" + "" + "" + "urn:uuid:94b0ef77-0621-4086-95a2-85432fa97d40" + "urn:uuid:6978c106-95bc-424b-a17c-628206a5892d" + "" + "" + "urn:uuid:2ce499f2-59bc-4053-87bc-80f4b7e7b73e" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535" + "" + "" + "" + "" + "urn:uuid:9ac3b905-c599-4da8-8f0f-fc07e619899d" + "urn:uuid:19ff6da1-be79-4235-8d04-42201ad06e65" + "" + "" + "urn:uuid:0239017b-2ad9-4235-b46d-c4c1126e29fc" + "36" + "urn:uuid:f00e49a8-0dec-4e6c-95e7-078df988b751" + "urn:uuid:bd6272b6-511e-47c1-93bc-d56ebd314a70" + "" + "" + "" + "" + "" + "" + ""; + +const char *cpl_bad_doc = ""; + +const char *asset_map_doc = + "" + "" + "urn:uuid:68d9f591-8191-46b5-38b4-affb87a14132" + "IMF_TEST_ASSET_MAP" + "Some tool" + "1" + "2021-06-07T12:00:00+00:00" + "FFmpeg" + "" + "" + "urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0" + "" + "" + "IMF_TEST_ASSET_MAP_video.mxf" + "1" + "0" + "1234567" + "" + "" + "" + "" + "urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a" + "" + "" + "IMF_TEST_ASSET_MAP_video_1.mxf" + "1" + "0" + "234567" + "" + "" + "" + "" + "urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6" + "" + "" + "IMF_TEST_ASSET_MAP_audio.mxf" + "1" + "0" + "34567" + "" + "" + "" + "" + "urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686" + "" + "" + "CPL_IMF_TEST_ASSET_MAP.xml" + "1" + "0" + "12345" + "" + "" + "" + "" + "urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d" + "true" + "" + "" + "PKL_IMF_TEST_ASSET_MAP.xml" + "1" + "0" + "2345" + "" + "" + "" + "" + ""; + +static int test_cpl_parsing(void) +{ + xmlDocPtr doc; + FFIMFCPL *cpl; + int ret; + + doc = xmlReadMemory(cpl_doc, strlen(cpl_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("XML parsing failed.\n"); + return 1; + } + + ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); + xmlFreeDoc(doc); + if (ret) { + printf("CPL parsing failed.\n"); + return 1; + } + + printf("%s\n", cpl->content_title_utf8); + printf(FF_IMF_UUID_FORMAT "\n", UID_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); + for (uint32_t i = 0; i < cpl->main_markers_track->resource_count; i++) { + printf("Marker resource %" PRIu32 "\n", i); + for (uint32_t j = 0; j < cpl->main_markers_track->resources[i].marker_count; j++) { + printf(" Marker %" PRIu32 "\n", j); + printf(" Label %s\n", cpl->main_markers_track->resources[i].markers[j].label_utf8); + printf(" Offset %" PRIu32 "\n", cpl->main_markers_track->resources[i].markers[j].offset); + } + } + + 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("Main audio track count: %" PRIu32 "\n", cpl->main_audio_track_count); + for (uint32_t i = 0; i < cpl->main_audio_track_count; i++) { + printf(" Main audio virtual track %" PRIu32 "\n", i); + 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)); + } + } + + ff_imf_cpl_free(cpl); + + return 0; +} + +static int test_bad_cpl_parsing(void) +{ + xmlDocPtr doc; + FFIMFCPL *cpl; + int ret; + + doc = xmlReadMemory(cpl_bad_doc, strlen(cpl_bad_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("XML parsing failed.\n"); + return 1; + } + + ret = ff_imf_parse_cpl_from_xml_dom(doc, &cpl); + xmlFreeDoc(doc); + if (ret) { + printf("CPL parsing failed.\n"); + return ret; + } + + return 0; +} + +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)); + + 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)); + return 1; + } + } + + printf("\tCompare %s to %s.\n", asset->absolute_uri, expected_asset->absolute_uri); + if (strcmp(asset->absolute_uri, expected_asset->absolute_uri) != 0) { + printf("Invalid asset locator URI: found %s instead of %s expected.\n", + asset->absolute_uri, + expected_asset->absolute_uri); + return 1; + } + + return 0; +} + +static IMFAssetLocator ASSET_MAP_EXPECTED_LOCATORS[5] = { + {.uuid = {0xb5, 0xd6, 0x74, 0xb8, 0xc6, 0xce, 0x4b, 0xce, 0x3b, 0xdf, 0xbe, 0x04, 0x5d, 0xfd, 0xb2, 0xd0}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_video.mxf"}, + {.uuid = {0xec, 0x34, 0x67, 0xec, 0xab, 0x2a, 0x4f, 0x49, 0xc8, 0xcb, 0x89, 0xca, 0xa3, 0x76, 0x1f, 0x4a}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_video_1.mxf"}, + {.uuid = {0x5c, 0xf5, 0xb5, 0xa7, 0x8b, 0xb3, 0x4f, 0x08, 0xea, 0xa6, 0x35, 0x33, 0xd4, 0xb7, 0x7f, 0xa6}, + .absolute_uri = (char *)"IMF_TEST_ASSET_MAP_audio.mxf"}, + {.uuid = {0x55, 0x97, 0x77, 0xd6, 0xec, 0x29, 0x43, 0x75, 0xf9, 0x0d, 0x30, 0x0b, 0x0b, 0xf7, 0x36, 0x86}, + .absolute_uri = (char *)"CPL_IMF_TEST_ASSET_MAP.xml"}, + {.uuid = {0xdd, 0x04, 0x52, 0x8d, 0x9b, 0x80, 0x45, 0x2a, 0x7a, 0x13, 0x80, 0x5b, 0x08, 0x27, 0x8b, 0x3d}, + .absolute_uri = (char *)"PKL_IMF_TEST_ASSET_MAP.xml"}, +}; + +static int test_asset_map_parsing(void) +{ + IMFAssetLocatorMap asset_locator_map; + xmlDoc *doc; + int ret; + + doc = xmlReadMemory(asset_map_doc, strlen(asset_map_doc), NULL, NULL, 0); + if (doc == NULL) { + printf("Asset map XML parsing failed.\n"); + return 1; + } + + printf("Allocate asset map\n"); + imf_asset_locator_map_init(&asset_locator_map); + + printf("Parse asset map XML document\n"); + ret = parse_imf_asset_map_from_xml_dom(NULL, doc, &asset_locator_map, doc->name); + if (ret) { + printf("Asset map parsing failed.\n"); + goto cleanup; + } + + printf("Compare assets count: %d to 5\n", asset_locator_map.asset_count); + if (asset_locator_map.asset_count != 5) { + printf("Asset map parsing failed: found %d assets instead of 5 expected.\n", + asset_locator_map.asset_count); + ret = 1; + goto cleanup; + } + + for (uint32_t i = 0; i < asset_locator_map.asset_count; ++i) { + printf("For asset: %d:\n", i); + ret = check_asset_locator_attributes(&(asset_locator_map.assets[i]), + &(ASSET_MAP_EXPECTED_LOCATORS[i])); + if (ret > 0) + goto cleanup; + } + +cleanup: + imf_asset_locator_map_deinit(&asset_locator_map); + xmlFreeDoc(doc); + return ret; +} + +typedef struct PathTypeTestStruct { + const char *path; + int is_url; + int is_unix_absolute_path; + int is_dos_absolute_path; +} PathTypeTestStruct; + +static const PathTypeTestStruct PATH_TYPE_TEST_STRUCTS[11] = { + {.path = "file://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "http://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "https://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "s3://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "ftp://path/to/somewhere", .is_url = 1, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "/path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 1, .is_dos_absolute_path = 0}, + {.path = "path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, + {.path = "C:\\path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "C:/path/to/somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "\\\\path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 1}, + {.path = "path\\to\\somewhere", .is_url = 0, .is_unix_absolute_path = 0, .is_dos_absolute_path = 0}, +}; + +static int test_path_type_functions(void) +{ + PathTypeTestStruct path_type; + for (uint32_t i = 0; i < 11; ++i) { + path_type = PATH_TYPE_TEST_STRUCTS[i]; + if (imf_uri_is_url(path_type.path) != path_type.is_url) { + fprintf(stderr, + "URL comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_url, + !path_type.is_url); + goto fail; + } + + if (imf_uri_is_unix_abs_path(path_type.path) != path_type.is_unix_absolute_path) { + fprintf(stderr, + "Unix absolute path comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_unix_absolute_path, + !path_type.is_unix_absolute_path); + goto fail; + } + + if (imf_uri_is_dos_abs_path(path_type.path) != path_type.is_dos_absolute_path) { + fprintf(stderr, + "DOS absolute path comparison test failed for '%s', got %d instead of expected %d\n", + path_type.path, + path_type.is_dos_absolute_path, + !path_type.is_dos_absolute_path); + goto fail; + } + } + + return 0; + +fail: + return 1; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + if (test_cpl_parsing() != 0) + ret = 1; + + if (test_asset_map_parsing() != 0) + ret = 1; + + if (test_path_type_functions() != 0) + ret = 1; + + printf("#### The following should fail ####\n"); + if (test_bad_cpl_parsing() == 0) + ret = 1; + printf("#### End failing test ####\n"); + + return ret; +} diff --git a/libavformat/tests/movenc.c b/libavformat/tests/movenc.c index 04155dde76..2af72f11c7 100644 --- a/libavformat/tests/movenc.c +++ b/libavformat/tests/movenc.c @@ -186,7 +186,7 @@ static void init_fps(int bf, int audio_preroll, int fps) ctx->oformat = av_guess_format(format, NULL, NULL); if (!ctx->oformat) exit(1); - ctx->pb = avio_alloc_context(iobuf, iobuf_size, AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL); + ctx->pb = avio_alloc_context(iobuf, iobuf_size, 1, NULL, NULL, io_write, NULL); if (!ctx->pb) exit(1); ctx->pb->write_data_type = io_write_data_type; diff --git a/libavformat/tls_mbedtls.c b/libavformat/tls_mbedtls.c index aadf17760d..5754d0d018 100644 --- a/libavformat/tls_mbedtls.c +++ b/libavformat/tls_mbedtls.c @@ -223,7 +223,7 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op } mbedtls_ssl_conf_authmode(&tls_ctx->ssl_config, - shr->ca_file ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); + shr->verify ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&tls_ctx->ssl_config, mbedtls_ctr_drbg_random, &tls_ctx->ctr_drbg_context); mbedtls_ssl_conf_ca_chain(&tls_ctx->ssl_config, &tls_ctx->ca_cert, NULL); diff --git a/libavformat/to_upper4.c b/libavformat/to_upper4.c new file mode 100644 index 0000000000..e84c803675 --- /dev/null +++ b/libavformat/to_upper4.c @@ -0,0 +1,23 @@ +/* + * Converting FOURCCs to uppercase + * Copyright (c) 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 "libavcodec/to_upper4.h" diff --git a/libavformat/ttaenc.c b/libavformat/ttaenc.c index 11855c32d9..486f8bdd10 100644 --- a/libavformat/ttaenc.c +++ b/libavformat/ttaenc.c @@ -30,7 +30,7 @@ typedef struct TTAMuxContext { AVIOContext *seek_table; - PacketList *queue, *queue_end; + PacketList queue; uint32_t nb_samples; int frame_size; int last_frame; @@ -94,11 +94,11 @@ static int tta_write_packet(AVFormatContext *s, AVPacket *pkt) TTAMuxContext *tta = s->priv_data; int ret; - ret = avpriv_packet_list_put(&tta->queue, &tta->queue_end, pkt, - av_packet_ref, 0); + ret = avpriv_packet_list_put(&tta->queue, pkt, NULL, 0); if (ret < 0) { return ret; } + pkt = &tta->queue.tail->pkt; avio_wl32(tta->seek_table, pkt->size); tta->nb_samples += pkt->duration; @@ -125,8 +125,8 @@ static void tta_queue_flush(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; AVPacket *const pkt = ffformatcontext(s)->pkt; - while (tta->queue) { - avpriv_packet_list_get(&tta->queue, &tta->queue_end, pkt); + while (tta->queue.head) { + avpriv_packet_list_get(&tta->queue, pkt); avio_write(s->pb, pkt->data, pkt->size); av_packet_unref(pkt); } @@ -162,7 +162,7 @@ static void tta_deinit(AVFormatContext *s) TTAMuxContext *tta = s->priv_data; ffio_free_dyn_buf(&tta->seek_table); - avpriv_packet_list_free(&tta->queue, &tta->queue_end); + avpriv_packet_list_free(&tta->queue); } const AVOutputFormat ff_tta_muxer = { diff --git a/libavformat/udp.c b/libavformat/udp.c index bbe5aecc46..180d96a988 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -623,7 +623,7 @@ end: /* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { - char hostname[1024], localaddr[1024] = ""; + char hostname[1024]; int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1; UDPContext *s = h->priv_data; int is_output; @@ -708,7 +708,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) s->burst_bits = strtoll(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { - av_strlcpy(localaddr, buf, sizeof(localaddr)); + av_freep(&s->localaddr); + s->localaddr = av_strdup(buf); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if ((ret = ff_ip_parse_sources(h, buf, &s->filters)) < 0) @@ -738,8 +739,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ - if (!(flags & AVIO_FLAG_READ)) + if (!(flags & AVIO_FLAG_READ)) { + ret = AVERROR(EINVAL); goto fail; + } } else { if ((ret = ff_udp_set_remote_url(h, uri)) < 0) goto fail; @@ -748,12 +751,11 @@ static int udp_open(URLContext *h, const char *uri, int flags) if ((s->is_multicast || s->local_port <= 0) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; - if (localaddr[0]) - udp_fd = udp_socket_create(h, &my_addr, &len, localaddr); - else - udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); - if (udp_fd < 0) + udp_fd = udp_socket_create(h, &my_addr, &len, s->localaddr); + if (udp_fd < 0) { + ret = AVERROR(EIO); goto fail; + } s->local_addr_storage=my_addr; //store for future multicast join diff --git a/libavformat/utils.c b/libavformat/utils.c index 509c0ecdce..e643821fc9 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -28,6 +28,7 @@ #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" @@ -238,7 +239,6 @@ int avformat_queue_attached_pictures(AVFormatContext *s) } ret = avpriv_packet_list_put(&si->raw_packet_buffer, - &si->raw_packet_buffer_end, &s->streams[i]->attached_pic, av_packet_ref, 0); if (ret < 0) @@ -299,11 +299,11 @@ int ff_is_intra_only(enum AVCodecID id) void ff_flush_packet_queue(AVFormatContext *s) { FFFormatContext *const si = ffformatcontext(s); - avpriv_packet_list_free(&si->parse_queue, &si->parse_queue_end); - avpriv_packet_list_free(&si->packet_buffer, &si->packet_buffer_end); - avpriv_packet_list_free(&si->raw_packet_buffer, &si->raw_packet_buffer_end); + 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_remaining_size = RAW_PACKET_BUFFER_SIZE; + si->raw_packet_buffer_size = 0; } int av_find_default_stream_index(AVFormatContext *s) @@ -360,7 +360,7 @@ enum AVCodecID ff_codec_get_id(const AVCodecTag *tags, unsigned int tag) if (tag == tags[i].tag) return tags[i].id; for (int i = 0; tags[i].id != AV_CODEC_ID_NONE; i++) - if (avpriv_toupper4(tag) == avpriv_toupper4(tags[i].tag)) + if (ff_toupper4(tag) == ff_toupper4(tags[i].tag)) return tags[i].id; return AV_CODEC_ID_NONE; } @@ -604,6 +604,15 @@ int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src) 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); @@ -721,6 +730,41 @@ void avformat_free_context(AVFormatContext *s) 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); @@ -745,6 +789,10 @@ AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c) 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; @@ -1111,6 +1159,7 @@ char *ff_data_to_hex(char *buff, const uint8_t *src, int s, int lowercase) buff[i * 2] = hex_table[src[i] >> 4]; buff[i * 2 + 1] = hex_table[src[i] & 0xF]; } + buff[2 * s] = '\0'; return buff; } @@ -1223,7 +1272,7 @@ void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, } } -int ff_find_stream_index(AVFormatContext *s, int id) +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) @@ -1366,8 +1415,9 @@ AVRational av_guess_frame_rate(AVFormatContext *format, AVStream *st, AVFrame *f * 0 if st is NOT a matching stream * >0 if st is a matching stream */ -static int match_stream_specifier(AVFormatContext *s, AVStream *st, - const char *spec, const char **indexptr, AVProgram **p) +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) { @@ -1434,32 +1484,32 @@ static int match_stream_specifier(AVFormatContext *s, AVStream *st, return AVERROR(EINVAL); return match && (stream_id == st->id); } else if (*spec == 'm' && *(spec + 1) == ':') { - AVDictionaryEntry *tag; + const AVDictionaryEntry *tag; char *key, *val; int ret; if (match) { - spec += 2; - val = strchr(spec, ':'); + spec += 2; + val = strchr(spec, ':'); - key = val ? av_strndup(spec, val - spec) : av_strdup(spec); - if (!key) - return AVERROR(ENOMEM); + 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; + 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); + av_freep(&key); } return match && ret; } else if (*spec == 'u' && *(spec + 1) == '\0') { - AVCodecParameters *par = st->codecpar; + const AVCodecParameters *par = st->codecpar; int val; switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -1495,7 +1545,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, int ret, index; char *endptr; const char *indexptr = NULL; - AVProgram *p = NULL; + const AVProgram *p = NULL; int nb_streams; ret = match_stream_specifier(s, st, spec, &indexptr, &p); @@ -1518,7 +1568,7 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, /* 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++) { - AVStream *candidate = p ? s->streams[p->stream_index[i]] : s->streams[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; @@ -1760,13 +1810,7 @@ int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *a } if (args && bsfc->filter->priv_class) { - const AVOption *opt = av_opt_next(bsfc->priv_data, NULL); - const char * shorthand[2] = {NULL}; - - if (opt) - shorthand[0] = opt->name; - - if ((ret = av_opt_set_from_string(bsfc->priv_data, args, shorthand, "=", ":")) < 0) { + if ((ret = av_set_options_string(bsfc->priv_data, args, "=", ":")) < 0) { av_bsf_free(&bsfc); return ret; } @@ -1795,11 +1839,22 @@ int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **op return 0; } -void ff_format_io_close(AVFormatContext *s, AVIOContext **pb) +void ff_format_io_close_default(AVFormatContext *s, AVIOContext *pb) { - if (*pb) - s->io_close(s, *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) { @@ -1950,3 +2005,88 @@ void ff_format_set_url(AVFormatContext *s, char *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/v210.c b/libavformat/v210.c deleted file mode 100644 index 24f71d4014..0000000000 --- a/libavformat/v210.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Raw v210 video demuxer - * Copyright (c) 2015 Tiancheng "Timothy" 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 "libavutil/imgutils.h" -#include "libavutil/parseutils.h" -#include "libavutil/pixdesc.h" -#include "libavutil/opt.h" -#include "internal.h" -#include "avformat.h" - -typedef struct V210DemuxerContext { - const AVClass *class; /**< Class for private options. */ - int width, height; /**< Integers describing video size, set by a private option. */ - AVRational framerate; /**< AVRational describing framerate, set by a private option. */ -} V210DemuxerContext; - -// v210 frame width is padded to multiples of 48 -#define GET_PACKET_SIZE(w, h) (((w + 47) / 48) * 48 * h * 8 / 3) - -static int v210_read_header(AVFormatContext *ctx) -{ - V210DemuxerContext *s = ctx->priv_data; - AVStream *st; - int ret; - - st = avformat_new_stream(ctx, NULL); - if (!st) - return AVERROR(ENOMEM); - - st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; - - st->codecpar->codec_id = ctx->iformat->raw_codec_id; - - avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); - - ret = av_image_check_size(s->width, s->height, 0, ctx); - if (ret < 0) - return ret; - st->codecpar->width = s->width; - st->codecpar->height = s->height; - st->codecpar->format = ctx->iformat->raw_codec_id == AV_CODEC_ID_V210 ? - AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_YUV422P16; - ctx->packet_size = GET_PACKET_SIZE(s->width, s->height); - st->codecpar->bit_rate = av_rescale_q(ctx->packet_size, - (AVRational){8,1}, st->time_base); - - return 0; -} - - -static int v210_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - int ret; - - ret = av_get_packet(s->pb, pkt, s->packet_size); - pkt->pts = pkt->dts = pkt->pos / s->packet_size; - - pkt->stream_index = 0; - if (ret < 0) - return ret; - return 0; -} - -#define OFFSET(x) offsetof(V210DemuxerContext, x) -#define DEC AV_OPT_FLAG_DECODING_PARAM -static const AVOption v210_options[] = { - { "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 }, -}; - -static const AVClass v210_demuxer_class = { - .class_name = "v210(x) demuxer", - .item_name = av_default_item_name, - .option = v210_options, - .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(V210DemuxerContext), - .read_header = v210_read_header, - .read_packet = v210_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(V210DemuxerContext), - .read_header = v210_read_header, - .read_packet = v210_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/version.h b/libavformat/version.h index d5dd22059b..bd014e907e 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -32,8 +32,8 @@ // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium) // Also please add any ticket numbers that you believe might be affected here #define LIBAVFORMAT_VERSION_MAJOR 59 -#define LIBAVFORMAT_VERSION_MINOR 6 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MINOR 17 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ @@ -55,15 +55,13 @@ * at once through the bump. This improves the git bisect-ability of the change. * */ -#ifndef FF_API_LAVF_PRIV_OPT #define FF_API_LAVF_PRIV_OPT (LIBAVFORMAT_VERSION_MAJOR < 60) -#endif -#ifndef FF_API_COMPUTE_PKT_FIELDS2 #define FF_API_COMPUTE_PKT_FIELDS2 (LIBAVFORMAT_VERSION_MAJOR < 60) -#endif +#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) -#ifndef FF_API_R_FRAME_RATE #define FF_API_R_FRAME_RATE 1 -#endif #endif /* AVFORMAT_VERSION_H */ diff --git a/libavformat/vivo.c b/libavformat/vivo.c index b2904cd25a..2a08e1df03 100644 --- a/libavformat/vivo.c +++ b/libavformat/vivo.c @@ -26,6 +26,7 @@ * @sa http://wiki.multimedia.cx/index.php?title=Vivo */ +#include "libavutil/avstring.h" #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" @@ -120,7 +121,7 @@ static int vivo_get_packet_header(AVFormatContext *s) static int vivo_read_header(AVFormatContext *s) { VivoContext *vivo = s->priv_data; - AVRational fps = { 1, 25}; + AVRational fps = { 0 }; AVStream *ast, *vst; unsigned char *line, *line_end, *key, *value; long value_int; @@ -206,17 +207,21 @@ static int vivo_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; value_used = 1; } else if (!strcmp(key, "FPS")) { - AVRational tmp; + double d; + if (av_sscanf(value, "%f", &d) != 1) + return AVERROR_INVALIDDATA; value_used = 1; - if (!av_parse_ratio(&tmp, value, 10000, AV_LOG_WARNING, s)) - fps = av_inv_q(tmp); + if (!fps.num && !fps.den) + fps = av_inv_q(av_d2q(d, 10000)); } if (!value_used) av_dict_set(&s->metadata, key, value, 0); } } + if (!fps.num || !fps.den) + fps = (AVRational){ 1, 25 }; avpriv_set_pts_info(ast, 64, 1, ast->codecpar->sample_rate); avpriv_set_pts_info(vst, 64, fps.num, fps.den); diff --git a/libavformat/westwood_vqa.c b/libavformat/westwood_vqa.c index bc4f53d4e3..9d116060a3 100644 --- a/libavformat/westwood_vqa.c +++ b/libavformat/westwood_vqa.c @@ -48,10 +48,14 @@ #define CINF_TAG MKBETAG('C', 'I', 'N', 'F') #define CINH_TAG MKBETAG('C', 'I', 'N', 'H') #define CIND_TAG MKBETAG('C', 'I', 'N', 'D') +#define LINF_TAG MKBETAG('L', 'I', 'N', 'F') #define PINF_TAG MKBETAG('P', 'I', 'N', 'F') #define PINH_TAG MKBETAG('P', 'I', 'N', 'H') #define PIND_TAG MKBETAG('P', 'I', 'N', 'D') #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S') +#define SN2J_TAG MKBETAG('S', 'N', '2', 'J') +#define VIEW_TAG MKBETAG('V', 'I', 'E', 'W') +#define ZBUF_TAG MKBETAG('Z', 'B', 'U', 'F') #define VQA_HEADER_SIZE 0x2A #define VQA_PREAMBLE_SIZE 8 @@ -143,11 +147,14 @@ static int wsvqa_read_header(AVFormatContext *s) case CINF_TAG: case CINH_TAG: case CIND_TAG: + case LINF_TAG: case PINF_TAG: case PINH_TAG: case PIND_TAG: case FINF_TAG: case CMDS_TAG: + case VIEW_TAG: + case ZBUF_TAG: break; default: @@ -292,6 +299,9 @@ static int wsvqa_read_packet(AVFormatContext *s, } else { switch(chunk_type){ case CMDS_TAG: + case SN2J_TAG: + case VIEW_TAG: + case ZBUF_TAG: break; default: av_log(s, AV_LOG_INFO, "Skipping unknown chunk %s\n", diff --git a/libavformat/wvenc.c b/libavformat/wvenc.c index 9a42f71440..0dca2f7996 100644 --- a/libavformat/wvenc.c +++ b/libavformat/wvenc.c @@ -30,7 +30,7 @@ typedef struct WvMuxContext { int64_t samples; } WvMuxContext; -static av_cold int wv_write_header(AVFormatContext *ctx) +static av_cold int wv_init(AVFormatContext *ctx) { if (ctx->nb_streams > 1 || ctx->streams[0]->codecpar->codec_id != AV_CODEC_ID_WAVPACK) { @@ -84,7 +84,7 @@ const AVOutputFormat ff_wv_muxer = { .priv_data_size = sizeof(WvMuxContext), .audio_codec = AV_CODEC_ID_WAVPACK, .video_codec = AV_CODEC_ID_NONE, - .write_header = wv_write_header, + .init = wv_init, .write_packet = wv_write_packet, .write_trailer = wv_write_trailer, .flags = AVFMT_NOTIMESTAMPS, diff --git a/libavutil/Makefile b/libavutil/Makefile index 410ac636f7..d17876df1a 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -195,6 +195,7 @@ OBJS += $(COMPAT_OBJS:%=../compat/%) # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += avutilres.o +SKIPHEADERS += objc.h SKIPHEADERS-$(HAVE_CUDA_H) += hwcontext_cuda.h SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda_internal.h \ cuda_check.h @@ -205,7 +206,9 @@ SKIPHEADERS-$(CONFIG_OPENCL) += hwcontext_opencl.h SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX) += hwcontext_videotoolbox.h SKIPHEADERS-$(CONFIG_VDPAU) += hwcontext_vdpau.h -SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h +SKIPHEADERS-$(CONFIG_VULKAN) += hwcontext_vulkan.h vulkan.h \ + vulkan_functions.h \ + vulkan_loader.h TESTPROGS = adler32 \ aes \ diff --git a/libavutil/aarch64/asm.S b/libavutil/aarch64/asm.S index d1fa72b3c6..bee91d59c3 100644 --- a/libavutil/aarch64/asm.S +++ b/libavutil/aarch64/asm.S @@ -36,6 +36,35 @@ # 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" + */ +#if defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT == 1) +# define GNU_PROPERTY_AARCH64_BTI (1 << 0) // Has BTI +# define AARCH64_VALID_CALL_TARGET hint #34 // BTI 'c' +# define AARCH64_VALID_JUMP_TARGET hint #38 // BTI 'j' +#else +# define GNU_PROPERTY_AARCH64_BTI 0 // No BTI +# define AARCH64_VALID_CALL_TARGET +# define AARCH64_VALID_JUMP_TARGET +#endif + +#if (GNU_PROPERTY_AARCH64_BTI != 0) + .pushsection .note.gnu.property, "a" + .balign 8 + .long 4 + .long 0x10 + .long 0x5 + .asciz "GNU" + .long 0xc0000000 /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 4 + .long GNU_PROPERTY_AARCH64_BTI + .long 0 + .popsection +#endif + .macro function name, export=0, align=2 .macro endfunc ELF .size \name, . - \name @@ -49,6 +78,7 @@ FUNC .endfunc ELF .type EXTERN_ASM\name, %function FUNC .func EXTERN_ASM\name EXTERN_ASM\name: + AARCH64_VALID_CALL_TARGET .else ELF .type \name, %function FUNC .func \name diff --git a/libavutil/aes_ctr.c b/libavutil/aes_ctr.c index 0c2e86785f..517d09cf96 100644 --- a/libavutil/aes_ctr.c +++ b/libavutil/aes_ctr.c @@ -22,15 +22,16 @@ #include "common.h" #include "aes_ctr.h" #include "aes.h" +#include "aes_internal.h" #include "random_seed.h" #define AES_BLOCK_SIZE (16) typedef struct AVAESCTR { - struct AVAES* aes; uint8_t counter[AES_BLOCK_SIZE]; uint8_t encrypted_counter[AES_BLOCK_SIZE]; int block_offset; + AVAES aes; } AVAESCTR; struct AVAESCTR *av_aes_ctr_alloc(void) @@ -68,12 +69,7 @@ void av_aes_ctr_set_random_iv(struct AVAESCTR *a) int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key) { - a->aes = av_aes_alloc(); - if (!a->aes) { - return AVERROR(ENOMEM); - } - - av_aes_init(a->aes, key, 128, 0); + av_aes_init(&a->aes, key, 128, 0); memset(a->counter, 0, sizeof(a->counter)); a->block_offset = 0; @@ -83,10 +79,7 @@ int av_aes_ctr_init(struct AVAESCTR *a, const uint8_t *key) void av_aes_ctr_free(struct AVAESCTR *a) { - if (a) { - av_freep(&a->aes); - av_free(a); - } + av_free(a); } static void av_aes_ctr_increment_be64(uint8_t* counter) @@ -116,7 +109,7 @@ void av_aes_ctr_crypt(struct AVAESCTR *a, uint8_t *dst, const uint8_t *src, int while (src < src_end) { if (a->block_offset == 0) { - av_aes_crypt(a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); + av_aes_crypt(&a->aes, a->encrypted_counter, a->counter, 1, NULL, 0); av_aes_ctr_increment_be64(a->counter + 8); } diff --git a/libavutil/bprint.c b/libavutil/bprint.c index a6849d7178..ea51d9b09c 100644 --- a/libavutil/bprint.c +++ b/libavutil/bprint.c @@ -244,10 +244,8 @@ int av_bprint_finalize(AVBPrint *buf, char **ret_str) str = buf->str; buf->str = NULL; } else { - str = av_malloc(real_size); - if (str) - memcpy(str, buf->str, real_size); - else + str = av_memdup(buf->str, real_size); + if (!str) ret = AVERROR(ENOMEM); } *ret_str = str; diff --git a/libavutil/common.h b/libavutil/common.h index 3cc1f07566..3eb9bc5f74 100644 --- a/libavutil/common.h +++ b/libavutil/common.h @@ -379,6 +379,8 @@ static av_always_inline int64_t av_sat_sub64_c(int64_t a, int64_t b) { /** * Clip a float value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. * @param a value to clip * @param amin minimum value of the clip range * @param amax maximum value of the clip range @@ -389,13 +391,13 @@ static av_always_inline av_const float av_clipf_c(float a, float amin, float ama #if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; + return FFMIN(FFMAX(a, amin), amax); } /** * Clip a double value into the amin-amax range. + * If a is nan or -inf amin will be returned. + * If a is +inf amax will be returned. * @param a value to clip * @param amin minimum value of the clip range * @param amax maximum value of the clip range @@ -406,9 +408,7 @@ static av_always_inline av_const double av_clipd_c(double a, double amin, double #if defined(HAVE_AV_CONFIG_H) && defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - if (a < amin) return amin; - else if (a > amax) return amax; - else return a; + return FFMIN(FFMAX(a, amin), amax); } /** Compute ceil(log2(x)). diff --git a/libavutil/cpu.c b/libavutil/cpu.c index 4627af4f23..1368502245 100644 --- a/libavutil/cpu.c +++ b/libavutil/cpu.c @@ -62,6 +62,8 @@ static int get_cpu_flags(void) return ff_get_cpu_flags_ppc(); if (ARCH_X86) return ff_get_cpu_flags_x86(); + if (ARCH_LOONGARCH) + return ff_get_cpu_flags_loongarch(); return 0; } @@ -135,6 +137,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" }, + { "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 #define CPU_FLAG_P3 CPU_FLAG_P2 | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_SSE @@ -168,6 +171,9 @@ int av_parse_cpu_caps(unsigned *flags, const char *s) #elif ARCH_MIPS { "mmi", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MMI }, .unit = "flags" }, { "msa", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_MSA }, .unit = "flags" }, +#elif ARCH_LOONGARCH + { "lsx", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_LSX }, .unit = "flags" }, + { "lasx", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_CPU_FLAG_LASX }, .unit = "flags" }, #endif { NULL }, }; @@ -253,6 +259,8 @@ size_t av_cpu_max_align(void) 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(); return 8; } diff --git a/libavutil/cpu.h b/libavutil/cpu.h index afea0640b4..ce9bf14bf7 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_SLOW_GATHER 0x2000000 ///< CPU has slow gathers. #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard #define AV_CPU_FLAG_VSX 0x0002 ///< ISA 2.06 @@ -72,6 +73,10 @@ #define AV_CPU_FLAG_MMI (1 << 0) #define AV_CPU_FLAG_MSA (1 << 1) +//Loongarch SIMD extension. +#define AV_CPU_FLAG_LSX (1 << 0) +#define AV_CPU_FLAG_LASX (1 << 1) + /** * Return the flags which specify extensions supported by the CPU. * The returned value is affected by av_force_cpu_flags() if that was used diff --git a/libavutil/cpu_internal.h b/libavutil/cpu_internal.h index 889764320b..e207b2d480 100644 --- a/libavutil/cpu_internal.h +++ b/libavutil/cpu_internal.h @@ -46,11 +46,13 @@ int ff_get_cpu_flags_aarch64(void); int ff_get_cpu_flags_arm(void); int ff_get_cpu_flags_ppc(void); int ff_get_cpu_flags_x86(void); +int ff_get_cpu_flags_loongarch(void); size_t ff_get_cpu_max_align_mips(void); size_t ff_get_cpu_max_align_aarch64(void); size_t ff_get_cpu_max_align_arm(void); size_t ff_get_cpu_max_align_ppc(void); size_t ff_get_cpu_max_align_x86(void); +size_t ff_get_cpu_max_align_loongarch(void); #endif /* AVUTIL_CPU_INTERNAL_H */ diff --git a/libavutil/display.h b/libavutil/display.h index 515adad795..d87bf68425 100644 --- a/libavutil/display.h +++ b/libavutil/display.h @@ -88,7 +88,7 @@ double av_display_rotation_get(const int32_t matrix[9]); /** - * Initialize a transformation matrix describing a pure counterclockwise + * Initialize a transformation matrix describing a pure clockwise * rotation by the specified angle (in degrees). * * @param matrix an allocated transformation matrix (will be fully overwritten diff --git a/libavutil/dovi_meta.c b/libavutil/dovi_meta.c index 7bd08f6c54..9c50da561e 100644 --- a/libavutil/dovi_meta.c +++ b/libavutil/dovi_meta.c @@ -33,3 +33,28 @@ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size) return dovi; } + +typedef struct AVDOVIMetadataInternal { + AVDOVIMetadata metadata; + AVDOVIRpuDataHeader header; + AVDOVIDataMapping mapping; + AVDOVIColorMetadata color; +} AVDOVIMetadataInternal; + +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +{ + AVDOVIMetadataInternal *dovi = av_mallocz(sizeof(AVDOVIMetadataInternal)); + if (!dovi) + return NULL; + + if (size) + *size = sizeof(*dovi); + + dovi->metadata = (struct AVDOVIMetadata) { + .header_offset = offsetof(AVDOVIMetadataInternal, header), + .mapping_offset = offsetof(AVDOVIMetadataInternal, mapping), + .color_offset = offsetof(AVDOVIMetadataInternal, color), + }; + + return &dovi->metadata; +} diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 299911d434..3d11e02bff 100644 --- a/libavutil/dovi_meta.h +++ b/libavutil/dovi_meta.h @@ -29,6 +29,7 @@ #include #include +#include "rational.h" /* * DOVI configuration @@ -67,4 +68,169 @@ typedef struct AVDOVIDecoderConfigurationRecord { */ AVDOVIDecoderConfigurationRecord *av_dovi_alloc(size_t *size); +/** + * Dolby Vision RPU data header. + * + * @note sizeof(AVDOVIRpuDataHeader) is not part of the public ABI. + */ +typedef struct AVDOVIRpuDataHeader { + uint8_t rpu_type; + uint16_t rpu_format; + uint8_t vdr_rpu_profile; + uint8_t vdr_rpu_level; + uint8_t chroma_resampling_explicit_filter_flag; + uint8_t coef_data_type; /* informative, lavc always converts to fixed */ + uint8_t coef_log2_denom; + uint8_t vdr_rpu_normalized_idc; + uint8_t bl_video_full_range_flag; + uint8_t bl_bit_depth; /* [8, 16] */ + uint8_t el_bit_depth; /* [8, 16] */ + uint8_t vdr_bit_depth; /* [8, 16] */ + uint8_t spatial_resampling_filter_flag; + uint8_t el_spatial_resampling_filter_flag; + uint8_t disable_residual_flag; +} AVDOVIRpuDataHeader; + +enum AVDOVIMappingMethod { + AV_DOVI_MAPPING_POLYNOMIAL = 0, + AV_DOVI_MAPPING_MMR = 1, +}; + +/** + * Coefficients of a piece-wise function. The pieces of the function span the + * value ranges between two adjacent pivot values. + */ +#define AV_DOVI_MAX_PIECES 8 +typedef struct AVDOVIReshapingCurve { + uint8_t num_pivots; /* [2, 9] */ + uint16_t pivots[AV_DOVI_MAX_PIECES + 1]; /* sorted ascending */ + enum AVDOVIMappingMethod mapping_idc[AV_DOVI_MAX_PIECES]; + /* AV_DOVI_MAPPING_POLYNOMIAL */ + uint8_t poly_order[AV_DOVI_MAX_PIECES]; /* [1, 2] */ + int64_t poly_coef[AV_DOVI_MAX_PIECES][3]; /* x^0, x^1, x^2 */ + /* AV_DOVI_MAPPING_MMR */ + uint8_t mmr_order[AV_DOVI_MAX_PIECES]; /* [1, 3] */ + int64_t mmr_constant[AV_DOVI_MAX_PIECES]; + int64_t mmr_coef[AV_DOVI_MAX_PIECES][3/* order - 1 */][7]; +} AVDOVIReshapingCurve; + +enum AVDOVINLQMethod { + AV_DOVI_NLQ_NONE = -1, + AV_DOVI_NLQ_LINEAR_DZ = 0, +}; + +/** + * Coefficients of the non-linear inverse quantization. For the interpretation + * of these, see ETSI GS CCM 001. + */ +typedef struct AVDOVINLQParams { + uint16_t nlq_offset; + uint64_t vdr_in_max; + /* AV_DOVI_NLQ_LINEAR_DZ */ + uint64_t linear_deadzone_slope; + uint64_t linear_deadzone_threshold; +} AVDOVINLQParams; + +/** + * Dolby Vision RPU data mapping parameters. + * + * @note sizeof(AVDOVIDataMapping) is not part of the public ABI. + */ +typedef struct AVDOVIDataMapping { + uint8_t vdr_rpu_id; + uint8_t mapping_color_space; + uint8_t mapping_chroma_format_idc; + AVDOVIReshapingCurve curves[3]; /* per component */ + + /* Non-linear inverse quantization */ + enum AVDOVINLQMethod nlq_method_idc; + uint32_t num_x_partitions; + uint32_t num_y_partitions; + AVDOVINLQParams nlq[3]; /* per component */ +} AVDOVIDataMapping; + +/** + * Dolby Vision RPU colorspace metadata parameters. + * + * @note sizeof(AVDOVIColorMetadata) is not part of the public ABI. + */ +typedef struct AVDOVIColorMetadata { + uint8_t dm_metadata_id; + uint8_t scene_refresh_flag; + + /** + * Coefficients of the custom Dolby Vision IPT-PQ matrices. These are to be + * used instead of the matrices indicated by the frame's colorspace tags. + * The output of rgb_to_lms_matrix is to be fed into a BT.2020 LMS->RGB + * matrix based on a Hunt-Pointer-Estevez transform, but without any + * crosstalk. (See the definition of the ICtCp colorspace for more + * information.) + */ + AVRational ycc_to_rgb_matrix[9]; /* before PQ linearization */ + AVRational ycc_to_rgb_offset[3]; /* input offset of neutral value */ + AVRational rgb_to_lms_matrix[9]; /* after PQ linearization */ + + /** + * Extra signal metadata (see Dolby patents for more info). + */ + uint16_t signal_eotf; + uint16_t signal_eotf_param0; + uint16_t signal_eotf_param1; + uint32_t signal_eotf_param2; + uint8_t signal_bit_depth; + uint8_t signal_color_space; + uint8_t signal_chroma_format; + uint8_t signal_full_range_flag; /* [0, 3] */ + uint16_t source_min_pq; + uint16_t source_max_pq; + uint16_t source_diagonal; +} AVDOVIColorMetadata; + +/** + * Combined struct representing a combination of header, mapping and color + * metadata, for attaching to frames as side data. + * + * @note The struct must be allocated with av_dovi_metadata_alloc() and + * its size is not a part of the public ABI. + */ + +typedef struct AVDOVIMetadata { + /** + * Offset in bytes from the beginning of this structure at which the + * respective structs start. + */ + size_t header_offset; /* AVDOVIRpuDataHeader */ + size_t mapping_offset; /* AVDOVIDataMapping */ + size_t color_offset; /* AVDOVIColorMetadata */ +} AVDOVIMetadata; + +static av_always_inline AVDOVIRpuDataHeader * +av_dovi_get_header(const AVDOVIMetadata *data) +{ + return (AVDOVIRpuDataHeader *)((uint8_t *) data + data->header_offset); +} + +static av_always_inline AVDOVIDataMapping * +av_dovi_get_mapping(const AVDOVIMetadata *data) +{ + return (AVDOVIDataMapping *)((uint8_t *) data + data->mapping_offset); +} + +static av_always_inline AVDOVIColorMetadata * +av_dovi_get_color(const AVDOVIMetadata *data) +{ + return (AVDOVIColorMetadata *)((uint8_t *) data + data->color_offset); +} + +/** + * Allocate an AVDOVIMetadata structure and initialize its + * fields to default values. + * + * @param size If this parameter is non-NULL, the size in bytes of the + * allocated struct will be written here on success + * + * @return the newly allocated struct or NULL on failure + */ +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size); + #endif /* AVUTIL_DOVI_META_H */ diff --git a/libavutil/fifo.c b/libavutil/fifo.c index 1060aedf13..d741bdd395 100644 --- a/libavutil/fifo.c +++ b/libavutil/fifo.c @@ -24,9 +24,10 @@ #include "common.h" #include "fifo.h" -static AVFifoBuffer *fifo_alloc_common(void *buffer, size_t size) +AVFifoBuffer *av_fifo_alloc_array(size_t nmemb, size_t size) { AVFifoBuffer *f; + void *buffer = av_realloc_array(NULL, nmemb, size); if (!buffer) return NULL; f = av_mallocz(sizeof(AVFifoBuffer)); @@ -35,21 +36,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) @@ -89,17 +83,31 @@ 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); + size_t offset_r = f->rptr - f->buffer; + size_t offset_w = f->wptr - f->buffer; + uint8_t *tmp; - if (!f2) + 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 +134,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 +147,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 +162,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,9 +194,11 @@ 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; + if (buf_size > av_fifo_size(f)) + return AVERROR(EINVAL); + do { int len = FFMIN(f->end - rptr, buf_size); if (func) @@ -200,7 +207,6 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, 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; @@ -213,7 +219,9 @@ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, 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 +230,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); diff --git a/libavutil/fifo.h b/libavutil/fifo.h index dc7bc6f0dd..f4fd291e59 100644 --- a/libavutil/fifo.h +++ b/libavutil/fifo.h @@ -91,6 +91,8 @@ 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 */ int av_fifo_generic_peek_at(AVFifoBuffer *f, void *dest, int offset, int buf_size, void (*func)(void*, void*, int)); @@ -101,6 +103,8 @@ 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 */ int av_fifo_generic_peek(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); @@ -110,6 +114,8 @@ 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 */ int av_fifo_generic_read(AVFifoBuffer *f, void *dest, int buf_size, void (*func)(void*, void*, int)); @@ -124,7 +130,7 @@ 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 */ int av_fifo_generic_write(AVFifoBuffer *f, void *src, int size, int (*func)(void*, void*, int)); @@ -156,6 +162,7 @@ int av_fifo_grow(AVFifoBuffer *f, unsigned int additional_space); */ 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 +172,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 av_fifo_generic_peek_at() */ +attribute_deprecated static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) { uint8_t *ptr = f->rptr + offs; @@ -175,5 +184,6 @@ static inline uint8_t *av_fifo_peek2(const AVFifoBuffer *f, int offs) ptr = f->end - (f->buffer - ptr); return ptr; } +#endif #endif /* AVUTIL_FIFO_H */ diff --git a/libavutil/frame.c b/libavutil/frame.c index 2617cda2b5..8997c85e35 100644 --- a/libavutil/frame.c +++ b/libavutil/frame.c @@ -52,9 +52,6 @@ const char *av_get_colorspace_name(enum AVColorSpace val) #endif static void get_frame_defaults(AVFrame *frame) { - if (frame->extended_data != frame->data) - av_freep(&frame->extended_data); - memset(frame, 0, sizeof(*frame)); frame->pts = @@ -63,6 +60,7 @@ static void get_frame_defaults(AVFrame *frame) frame->pkt_duration = 0; frame->pkt_pos = -1; frame->pkt_size = -1; + frame->time_base = (AVRational){ 0, 1 }; frame->key_frame = 1; frame->sample_aspect_ratio = (AVRational){ 0, 1 }; frame->format = -1; /* unknown */ @@ -98,12 +96,11 @@ static void wipe_side_data(AVFrame *frame) AVFrame *av_frame_alloc(void) { - AVFrame *frame = av_mallocz(sizeof(*frame)); + AVFrame *frame = av_malloc(sizeof(*frame)); if (!frame) return NULL; - frame->extended_data = NULL; get_frame_defaults(frame); return frame; @@ -278,6 +275,7 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy) dst->pkt_pos = src->pkt_pos; dst->pkt_size = src->pkt_size; dst->pkt_duration = src->pkt_duration; + dst->time_base = src->time_base; dst->reordered_opaque = src->reordered_opaque; dst->quality = src->quality; dst->best_effort_timestamp = src->best_effort_timestamp; @@ -455,6 +453,9 @@ void av_frame_unref(AVFrame *frame) av_buffer_unref(&frame->opaque_ref); av_buffer_unref(&frame->private_ref); + if (frame->extended_data != frame->data) + av_freep(&frame->extended_data); + get_frame_defaults(frame); } @@ -466,7 +467,6 @@ void av_frame_move_ref(AVFrame *dst, AVFrame *src) *dst = *src; if (src->extended_data == src->data) dst->extended_data = dst->data; - memset(src, 0, sizeof(*src)); get_frame_defaults(src); } @@ -728,6 +728,8 @@ const char *av_frame_side_data_name(enum AVFrameSideDataType type) case AV_FRAME_DATA_SEI_UNREGISTERED: return "H.26[45] User Data Unregistered SEI message"; case AV_FRAME_DATA_FILM_GRAIN_PARAMS: return "Film grain parameters"; case AV_FRAME_DATA_DETECTION_BBOXES: return "Bounding boxes for object detection and classification"; + case AV_FRAME_DATA_DOVI_RPU_BUFFER: return "Dolby Vision RPU Data"; + case AV_FRAME_DATA_DOVI_METADATA: return "Dolby Vision Metadata"; } return NULL; } diff --git a/libavutil/frame.h b/libavutil/frame.h index ff2540a20f..18e239f870 100644 --- a/libavutil/frame.h +++ b/libavutil/frame.h @@ -187,6 +187,20 @@ enum AVFrameSideDataType { * as described by AVDetectionBBoxHeader. */ AV_FRAME_DATA_DETECTION_BBOXES, + + /** + * Dolby Vision RPU raw data, suitable for passing to x265 + * or other libraries. Array of uint8_t, with NAL emulation + * bytes intact. + */ + AV_FRAME_DATA_DOVI_RPU_BUFFER, + + /** + * Parsed Dolby Vision metadata, suitable for passing to a software + * implementation. The payload is the AVDOVIMetadata struct defined in + * libavutil/dovi_meta.h. + */ + AV_FRAME_DATA_DOVI_METADATA, }; enum AVActiveFormatDescription { @@ -304,21 +318,32 @@ typedef struct AVFrame { #define AV_NUM_DATA_POINTERS 8 /** * pointer to the picture/channel planes. - * This might be different from the first allocated byte + * This might be different from the first allocated byte. For video, + * it could even point to the end of the image data. + * + * All pointers in data and extended_data must point into one of the + * AVBufferRef in buf or extended_buf. * * Some decoders access areas outside 0,0 - width,height, please * see avcodec_align_dimensions2(). Some filters and swscale can read * up to 16 bytes beyond the planes, if these filters are to be used, * then 16 extra bytes must be allocated. * - * NOTE: Except for hwaccel formats, pointers not needed by the format - * MUST be set to NULL. + * NOTE: Pointers not needed by the format MUST be set to NULL. + * + * @attention In case of video, the data[] pointers can point to the + * end of image data in order to reverse line order, when used in + * combination with negative values in the linesize[] array. */ uint8_t *data[AV_NUM_DATA_POINTERS]; /** - * For video, size in bytes of each picture line. - * For audio, size in bytes of each plane. + * For video, a positive or negative value, which is typically indicating + * the size in bytes of each picture line, but it can also be: + * - the negative byte size of lines for vertical flipping + * (with data[n] pointing to the end of the data + * - a positive or negative multiple of the byte size as for accessing + * even and odd fields of a frame (possibly flipped) * * For audio, only linesize[0] may be set. For planar audio, each channel * plane must be the same size. @@ -330,6 +355,9 @@ typedef struct AVFrame { * * @note The linesize may be larger than the size of usable data -- there * may be extra padding present for performance reasons. + * + * @attention In case of video, line size values can be negative to achieve + * a vertically inverted iteration over image lines. */ int linesize[AV_NUM_DATA_POINTERS]; @@ -402,6 +430,14 @@ typedef struct AVFrame { */ int64_t pkt_dts; + /** + * Time base for the timestamps in this frame. + * In the future, this field may be set on frames output by decoders or + * filters, but its value will be by default ignored on input to encoders + * or filters. + */ + AVRational time_base; + /** * picture number in bitstream order */ @@ -463,10 +499,10 @@ typedef struct AVFrame { uint64_t channel_layout; /** - * AVBuffer references backing the data for this frame. If all elements of - * this array are NULL, then this frame is not reference counted. This array - * must be filled contiguously -- if buf[i] is non-NULL then buf[j] must - * also be non-NULL for all j < i. + * AVBuffer references backing the data for this frame. All the pointers in + * data and extended_data must point inside one of the buffers in buf or + * extended_buf. This array must be filled contiguously -- if buf[i] is + * non-NULL then buf[j] must also be non-NULL for all j < i. * * There may be at most one AVBuffer per data plane, so for video this array * always contains all the references. For planar audio with more than diff --git a/libavutil/hwcontext_cuda.c b/libavutil/hwcontext_cuda.c index 48f7ecbdd3..b96460920f 100644 --- a/libavutil/hwcontext_cuda.c +++ b/libavutil/hwcontext_cuda.c @@ -376,6 +376,22 @@ static int cuda_context_init(AVHWDeviceContext *device_ctx, int flags) { return 0; } +static int cuda_flags_from_opts(AVHWDeviceContext *device_ctx, + AVDictionary *opts, int *flags) +{ + AVDictionaryEntry *primary_ctx_opt = av_dict_get(opts, "primary_ctx", NULL, 0); + + if (primary_ctx_opt && strtol(primary_ctx_opt->value, NULL, 10)) { + av_log(device_ctx, AV_LOG_VERBOSE, "Using CUDA primary device context\n"); + *flags |= AV_CUDA_USE_PRIMARY_CONTEXT; + } else if (primary_ctx_opt) { + av_log(device_ctx, AV_LOG_VERBOSE, "Disabling use of CUDA primary device context\n"); + *flags &= ~AV_CUDA_USE_PRIMARY_CONTEXT; + } + + return 0; +} + static int cuda_device_create(AVHWDeviceContext *device_ctx, const char *device, AVDictionary *opts, int flags) @@ -384,10 +400,15 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx, CudaFunctions *cu; int ret, device_idx = 0; + ret = cuda_flags_from_opts(device_ctx, opts, &flags); + if (ret < 0) + goto error; + if (device) device_idx = strtol(device, NULL, 0); - if (cuda_device_init(device_ctx) < 0) + ret = cuda_device_init(device_ctx); + if (ret < 0) goto error; cu = hwctx->internal->cuda_dl; @@ -408,7 +429,7 @@ static int cuda_device_create(AVHWDeviceContext *device_ctx, error: cuda_device_uninit(device_ctx); - return AVERROR_UNKNOWN; + return ret; } static int cuda_device_derive(AVHWDeviceContext *device_ctx, @@ -419,6 +440,10 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, const char *src_uuid = NULL; int ret, i, device_count; + ret = cuda_flags_from_opts(device_ctx, opts, &flags); + if (ret < 0) + goto error; + #if CONFIG_VULKAN VkPhysicalDeviceIDProperties vk_idp = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES, @@ -442,16 +467,19 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, #undef TYPE #endif default: - return AVERROR(ENOSYS); + ret = AVERROR(ENOSYS); + goto error; } if (!src_uuid) { av_log(device_ctx, AV_LOG_ERROR, "Failed to get UUID of source device.\n"); + ret = AVERROR(EINVAL); goto error; } - if (cuda_device_init(device_ctx) < 0) + ret = cuda_device_init(device_ctx); + if (ret < 0) goto error; cu = hwctx->internal->cuda_dl; @@ -496,7 +524,7 @@ static int cuda_device_derive(AVHWDeviceContext *device_ctx, error: cuda_device_uninit(device_ctx); - return AVERROR_UNKNOWN; + return ret; } const HWContextType ff_hwcontext_type_cuda = { diff --git a/libavutil/hwcontext_dxva2.c b/libavutil/hwcontext_dxva2.c index f3e578fc10..53d00fa815 100644 --- a/libavutil/hwcontext_dxva2.c +++ b/libavutil/hwcontext_dxva2.c @@ -83,6 +83,7 @@ static const struct { { MKTAG('N', 'V', '1', '2'), AV_PIX_FMT_NV12 }, { MKTAG('P', '0', '1', '0'), AV_PIX_FMT_P010 }, { D3DFMT_P8, AV_PIX_FMT_PAL8 }, + { D3DFMT_A8R8G8B8, AV_PIX_FMT_BGRA }, }; DEFINE_GUID(video_decoder_service, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02); diff --git a/libavutil/hwcontext_qsv.c b/libavutil/hwcontext_qsv.c index c18747f7eb..853fb7f60d 100644 --- a/libavutil/hwcontext_qsv.c +++ b/libavutil/hwcontext_qsv.c @@ -47,6 +47,7 @@ #include "pixfmt.h" #include "pixdesc.h" #include "time.h" +#include "imgutils.h" #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \ (MFX_VERSION_MAJOR > (MAJOR) || \ @@ -90,6 +91,7 @@ typedef struct QSVFramesContext { mfxExtOpaqueSurfaceAlloc opaque_alloc; mfxExtBuffer *ext_buffers[1]; + AVFrame realigned_tmp_frame; } QSVFramesContext; static const struct { @@ -137,6 +139,54 @@ static uint32_t qsv_get_d3d11va_bind_flags(int mem_type) } #endif +static int qsv_fill_border(AVFrame *dst, const AVFrame *src) +{ + const AVPixFmtDescriptor *desc; + int i, planes_nb = 0; + if (dst->format != src->format) + return AVERROR(EINVAL); + + desc = av_pix_fmt_desc_get(dst->format); + + for (i = 0; i < desc->nb_components; i++) + planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1); + + for (i = 0; i < planes_nb; i++) { + int sheight, dheight, y; + ptrdiff_t swidth = av_image_get_linesize(src->format, + src->width, + i); + ptrdiff_t dwidth = av_image_get_linesize(dst->format, + dst->width, + i); + const AVComponentDescriptor comp = desc->comp[i]; + if (swidth < 0 || dwidth < 0) { + av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n"); + return AVERROR(EINVAL); + } + sheight = src->height; + dheight = dst->height; + if (i) { + sheight = AV_CEIL_RSHIFT(src->height, desc->log2_chroma_h); + dheight = AV_CEIL_RSHIFT(dst->height, desc->log2_chroma_h); + } + //fill right padding + for (y = 0; y < sheight; y++) { + void *line_ptr = dst->data[i] + y*dst->linesize[i] + swidth; + av_memcpy_backptr(line_ptr, + comp.depth > 8 ? 2 : 1, + dwidth - swidth); + } + //fill bottom padding + for (y = sheight; y < dheight; y++) { + memcpy(dst->data[i]+y*dst->linesize[i], + dst->data[i]+(sheight-1)*dst->linesize[i], + dwidth); + } + } + return 0; +} + static int qsv_device_init(AVHWDeviceContext *ctx) { AVQSVDeviceContext *hwctx = ctx->hwctx; @@ -220,6 +270,7 @@ static void qsv_frames_uninit(AVHWFramesContext *ctx) av_freep(&s->surface_ptrs); av_freep(&s->surfaces_internal); av_freep(&s->handle_pairs_internal); + av_frame_unref(&s->realigned_tmp_frame); av_buffer_unref(&s->child_frames_ref); } @@ -235,8 +286,6 @@ static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size) if (s->nb_surfaces_used < hwctx->nb_surfaces) { s->nb_surfaces_used++; - av_buffer_create((uint8_t*)(s->handle_pairs_internal + s->nb_surfaces_used - 1), - sizeof(*s->handle_pairs_internal), qsv_pool_release_dummy, NULL, 0); return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1), sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0); } @@ -1016,12 +1065,13 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, QSVFramesContext *s = ctx->internal->priv; mfxFrameSurface1 in = {{ 0 }}; mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3]; + mfxFrameInfo tmp_info; mfxSyncPoint sync = NULL; mfxStatus err; int ret = 0; /* make a copy if the input is not padded as libmfx requires */ - AVFrame tmp_frame; + AVFrame *tmp_frame = &s->realigned_tmp_frame; const AVFrame *src_frame; int realigned = 0; @@ -1050,24 +1100,40 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, 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 uploading. */ if (src->height & 15 || src->linesize[0] & 15) { realigned = 1; - memset(&tmp_frame, 0, sizeof(tmp_frame)); - tmp_frame.format = src->format; - tmp_frame.width = FFALIGN(src->width, 16); - tmp_frame.height = FFALIGN(src->height, 16); - ret = av_frame_get_buffer(&tmp_frame, 0); - if (ret < 0) - return ret; + if (tmp_frame->format != src->format || + tmp_frame->width != FFALIGN(src->width, 16) || + tmp_frame->height != FFALIGN(src->height, 16)) { + av_frame_unref(tmp_frame); - ret = av_frame_copy(&tmp_frame, src); + tmp_frame->format = src->format; + tmp_frame->width = FFALIGN(src->width, 16); + tmp_frame->height = FFALIGN(src->height, 16); + ret = av_frame_get_buffer(tmp_frame, 0); + if (ret < 0) + return ret; + } + ret = av_frame_copy(tmp_frame, src); if (ret < 0) { - av_frame_unref(&tmp_frame); + av_frame_unref(tmp_frame); return ret; } + ret = qsv_fill_border(tmp_frame, src); + if (ret < 0) { + av_frame_unref(tmp_frame); + return ret; + } + + tmp_info = out->Info; + out->Info.CropW = FFMIN(out->Info.Width, tmp_frame->width); + out->Info.CropH = FFMIN(out->Info.Height, tmp_frame->height); } - src_frame = realigned ? &tmp_frame : src; + src_frame = realigned ? tmp_frame : src; if (!s->session_upload) { if (s->child_frames_ref) @@ -1099,8 +1165,10 @@ static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, return AVERROR_UNKNOWN; } - if (realigned) - av_frame_unref(&tmp_frame); + if (realigned) { + out->Info.CropW = tmp_info.CropW; + out->Info.CropH = tmp_info.CropH; + } return 0; } @@ -1220,7 +1288,7 @@ static int qsv_map_to(AVHWFramesContext *dst_ctx, case AV_PIX_FMT_VAAPI: { mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId; - if (pair->first == src->data[3]) { + if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) { index = i; break; } @@ -1465,10 +1533,10 @@ static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, e = av_dict_get(opts, "child_device_type", NULL, 0); if (e) { - child_device_type = av_hwdevice_find_type_by_name(e ? e->value : NULL); + child_device_type = av_hwdevice_find_type_by_name(e->value); if (child_device_type == AV_HWDEVICE_TYPE_NONE) { av_log(ctx, AV_LOG_ERROR, "Unknown child device type " - "\"%s\".\n", e ? e->value : NULL); + "\"%s\".\n", e->value); return AVERROR(EINVAL); } } else if (CONFIG_VAAPI) { diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c index 83e542876d..994b744e4d 100644 --- a/libavutil/hwcontext_vaapi.c +++ b/libavutil/hwcontext_vaapi.c @@ -79,6 +79,9 @@ typedef struct VAAPIFramesContext { unsigned int rt_format; // Whether vaDeriveImage works. int derive_works; + // Caches whether VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2 is unsupported for + // surface imports. + int prime_2_import_unsupported; } VAAPIFramesContext; typedef struct VAAPIMapping { @@ -989,6 +992,7 @@ static const struct { } vaapi_drm_format_map[] = { #ifdef DRM_FORMAT_R8 DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_RG88), + DRM_MAP(NV12, 2, DRM_FORMAT_R8, DRM_FORMAT_GR88), #endif DRM_MAP(NV12, 1, DRM_FORMAT_NV12), #if defined(VA_FOURCC_P010) && defined(DRM_FORMAT_R16) @@ -1022,32 +1026,17 @@ 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) { + VAAPIFramesContext *src_vafc = src_fc->internal->priv; AVHWFramesContext *dst_fc = (AVHWFramesContext*)dst->hw_frames_ctx->data; AVVAAPIDeviceContext *dst_dev = dst_fc->device_ctx->hwctx; const AVDRMFrameDescriptor *desc; const VAAPIFormatDescriptor *format_desc; VASurfaceID surface_id; - VAStatus vas; + VAStatus vas = VA_STATUS_SUCCESS; + int use_prime2; uint32_t va_fourcc; - int err, i, j, k; - - 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, - } - }; + int err, i, j; desc = (AVDRMFrameDescriptor*)src->data[0]; @@ -1083,35 +1072,117 @@ static int vaapi_map_from_drm(AVHWFramesContext *src_fc, AVFrame *dst, format_desc = vaapi_format_from_fourcc(va_fourcc); av_assert0(format_desc); - 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; + use_prime2 = !src_vafc->prime_2_import_unsupported && + desc->objects[0].format_modifier != DRM_FORMAT_MOD_INVALID; + if (use_prime2) { + VADRMPRIMESurfaceDescriptor prime_desc; + VASurfaceAttrib prime_attrs[2] = { + { + .type = VASurfaceAttribMemoryType, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypeInteger, + .value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2, + }, + { + .type = VASurfaceAttribExternalBufferDescriptor, + .flags = VA_SURFACE_ATTRIB_SETTABLE, + .value.type = VAGenericValueTypePointer, + .value.value.p = &prime_desc, + } + }; + prime_desc.fourcc = va_fourcc; + prime_desc.width = src_fc->width; + prime_desc.height = src_fc->height; + prime_desc.num_objects = desc->nb_objects; + for (i = 0; i < desc->nb_objects; ++i) { + prime_desc.objects[i].fd = desc->objects[i].fd; + prime_desc.objects[i].size = desc->objects[i].size; + prime_desc.objects[i].drm_format_modifier = + desc->objects[i].format_modifier; } - } - 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]); + prime_desc.num_layers = desc->nb_layers; + for (i = 0; i < desc->nb_layers; ++i) { + prime_desc.layers[i].drm_format = desc->layers[i].format; + prime_desc.layers[i].num_planes = desc->layers[i].nb_planes; + for (j = 0; j < desc->layers[i].nb_planes; ++j) { + prime_desc.layers[i].object_index[j] = + desc->layers[i].planes[j].object_index; + prime_desc.layers[i].offset[j] = desc->layers[i].planes[j].offset; + prime_desc.layers[i].pitch[j] = desc->layers[i].planes[j].pitch; + } + + if (format_desc->chroma_planes_swapped && + desc->layers[i].nb_planes == 3) { + FFSWAP(uint32_t, prime_desc.layers[i].pitch[1], + prime_desc.layers[i].pitch[2]); + FFSWAP(uint32_t, prime_desc.layers[i].offset[1], + prime_desc.layers[i].offset[2]); + } + } + + /* + * We can query for PRIME_2 support with vaQuerySurfaceAttributes, but that + * that needs the config_id which we don't have here . Both Intel and + * Gallium seem to do the correct error checks, so lets just try the + * PRIME_2 import first. + */ + vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, + src->width, src->height, &surface_id, 1, + prime_attrs, FF_ARRAY_ELEMS(prime_attrs)); + if (vas != VA_STATUS_SUCCESS) + src_vafc->prime_2_import_unsupported = 1; } - vas = vaCreateSurfaces(dst_dev->display, format_desc->rt_format, - src->width, src->height, - &surface_id, 1, - attrs, FF_ARRAY_ELEMS(attrs)); + if (!use_prime2 || vas != VA_STATUS_SUCCESS) { + int k; + unsigned long buffer_handle; + VASurfaceAttribExternalBuffers buffer_desc; + VASurfaceAttrib buffer_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, + } + }; + + 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, + buffer_attrs, FF_ARRAY_ELEMS(buffer_attrs)); + } 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 58095a1fc9..026127d412 100644 --- a/libavutil/hwcontext_videotoolbox.c +++ b/libavutil/hwcontext_videotoolbox.c @@ -48,18 +48,64 @@ static const struct { #ifdef kCFCoreFoundationVersionNumber10_7 { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV12 }, { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV12 }, + { kCVPixelFormatType_4444AYpCbCr16, false, AV_PIX_FMT_AYUV64 }, #endif #if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P010 }, { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P010 }, #endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV16 }, + { kCVPixelFormatType_422YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV16 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P210 }, + { kCVPixelFormatType_422YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P210 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + { kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P216 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange, false, AV_PIX_FMT_NV24 }, + { kCVPixelFormatType_444YpCbCr8BiPlanarFullRange, true, AV_PIX_FMT_NV24 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange, false, AV_PIX_FMT_P410 }, + { kCVPixelFormatType_444YpCbCr10BiPlanarFullRange, true, AV_PIX_FMT_P410 }, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + { kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange, false, AV_PIX_FMT_P416 }, +#endif }; static const enum AVPixelFormat supported_formats[] = { +#ifdef kCFCoreFoundationVersionNumber10_7 AV_PIX_FMT_NV12, + AV_PIX_FMT_AYUV64, +#endif AV_PIX_FMT_YUV420P, AV_PIX_FMT_UYVY422, +#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE AV_PIX_FMT_P010, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV16, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P210, +#endif +#if HAVE_KCVPIXELFORMATTYPE_422YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P216, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR8BIPLANARVIDEORANGE + AV_PIX_FMT_NV24, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR10BIPLANARVIDEORANGE + AV_PIX_FMT_P410, +#endif +#if HAVE_KCVPIXELFORMATTYPE_444YPCBCR16BIPLANARVIDEORANGE + AV_PIX_FMT_P416, +#endif AV_PIX_FMT_BGRA, }; @@ -272,7 +318,7 @@ static void vt_unmap(AVHWFramesContext *ctx, HWMapDescriptor *hwmap) CVPixelBufferUnlockBaseAddress(pixbuf, (uintptr_t)hwmap->priv); } -static int vt_pixbuf_set_par(AVHWFramesContext *hwfc, +static int vt_pixbuf_set_par(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { CFMutableDictionaryRef par = NULL; @@ -329,31 +375,30 @@ static int vt_pixbuf_set_par(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_chromaloc(AVHWFramesContext *hwfc, +CFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc) +{ + switch (loc) { + case AVCHROMA_LOC_LEFT: + return kCVImageBufferChromaLocation_Left; + case AVCHROMA_LOC_CENTER: + return kCVImageBufferChromaLocation_Center; + case AVCHROMA_LOC_TOP: + return kCVImageBufferChromaLocation_Top; + case AVCHROMA_LOC_BOTTOM: + return kCVImageBufferChromaLocation_Bottom; + case AVCHROMA_LOC_TOPLEFT: + return kCVImageBufferChromaLocation_TopLeft; + case AVCHROMA_LOC_BOTTOMLEFT: + return kCVImageBufferChromaLocation_BottomLeft; + default: + return NULL; + } +} + +static int vt_pixbuf_set_chromaloc(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { - CFStringRef loc = NULL; - - switch (src->chroma_location) { - case AVCHROMA_LOC_LEFT: - loc = kCVImageBufferChromaLocation_Left; - break; - case AVCHROMA_LOC_CENTER: - loc = kCVImageBufferChromaLocation_Center; - break; - case AVCHROMA_LOC_TOP: - loc = kCVImageBufferChromaLocation_Top; - break; - case AVCHROMA_LOC_BOTTOM: - loc = kCVImageBufferChromaLocation_Bottom; - break; - case AVCHROMA_LOC_TOPLEFT: - loc = kCVImageBufferChromaLocation_TopLeft; - break; - case AVCHROMA_LOC_BOTTOMLEFT: - loc = kCVImageBufferChromaLocation_BottomLeft; - break; - } + CFStringRef loc = av_map_videotoolbox_chroma_loc_from_av(src->chroma_location); if (loc) { CVBufferSetAttachment( @@ -366,103 +411,127 @@ static int vt_pixbuf_set_chromaloc(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, +CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space) +{ + switch (space) { + case AVCOL_SPC_BT2020_CL: + case AVCOL_SPC_BT2020_NCL: +#if HAVE_KCVIMAGEBUFFERYCBCRMATRIX_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferYCbCrMatrix_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_SPC_BT470BG: + case AVCOL_SPC_SMPTE170M: + return kCVImageBufferYCbCrMatrix_ITU_R_601_4; + case AVCOL_SPC_BT709: + return kCVImageBufferYCbCrMatrix_ITU_R_709_2; + case AVCOL_SPC_SMPTE240M: + return kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; + default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVYCbCrMatrixGetStringForIntegerCodePoint(space); +#endif + case AVCOL_SPC_UNSPECIFIED: + return NULL; + } +} + +CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri) +{ + switch (pri) { + case AVCOL_PRI_BT2020: +#if HAVE_KCVIMAGEBUFFERCOLORPRIMARIES_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferColorPrimaries_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_PRI_BT709: + return kCVImageBufferColorPrimaries_ITU_R_709_2; + case AVCOL_PRI_SMPTE170M: + return kCVImageBufferColorPrimaries_SMPTE_C; + case AVCOL_PRI_BT470BG: + return kCVImageBufferColorPrimaries_EBU_3213; + default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVColorPrimariesGetStringForIntegerCodePoint(pri); +#endif + case AVCOL_PRI_UNSPECIFIED: + return NULL; + } +} + +CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc) +{ + + switch (trc) { + case AVCOL_TRC_SMPTE2084: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_2084_PQ + if (__builtin_available(macOS 10.13, iOS 11, *)) + return kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; +#endif + return CFSTR("SMPTE_ST_2084_PQ"); + case AVCOL_TRC_BT2020_10: + case AVCOL_TRC_BT2020_12: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2020 + if (__builtin_available(macOS 10.11, iOS 9, *)) + return kCVImageBufferTransferFunction_ITU_R_2020; +#endif + return CFSTR("ITU_R_2020"); + case AVCOL_TRC_BT709: + return kCVImageBufferTransferFunction_ITU_R_709_2; + case AVCOL_TRC_SMPTE240M: + return kCVImageBufferTransferFunction_SMPTE_240M_1995; + case AVCOL_TRC_SMPTE428: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_SMPTE_ST_428_1 + if (__builtin_available(macOS 10.12, iOS 10, *)) + return kCVImageBufferTransferFunction_SMPTE_ST_428_1; +#endif + return CFSTR("SMPTE_ST_428_1"); + case AVCOL_TRC_ARIB_STD_B67: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, *)) + return kCVImageBufferTransferFunction_ITU_R_2100_HLG; +#endif + return CFSTR("ITU_R_2100_HLG"); + case AVCOL_TRC_GAMMA22: + return kCVImageBufferTransferFunction_UseGamma; + case AVCOL_TRC_GAMMA28: + return kCVImageBufferTransferFunction_UseGamma; + default: +#if HAVE_KCVIMAGEBUFFERTRANSFERFUNCTION_ITU_R_2100_HLG + if (__builtin_available(macOS 10.13, iOS 11, tvOS 11, watchOS 4, *)) + return CVTransferFunctionGetStringForIntegerCodePoint(trc); +#endif + case AVCOL_TRC_UNSPECIFIED: + return NULL; + } +} + +static int vt_pixbuf_set_colorspace(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { CFStringRef colormatrix = NULL, colorpri = NULL, colortrc = NULL; Float32 gamma = 0; - switch (src->colorspace) { - case AVCOL_SPC_BT2020_CL: - case AVCOL_SPC_BT2020_NCL: - if (__builtin_available(macOS 10.11, *)) - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_2020; - else - colormatrix = CFSTR("ITU_R_2020"); - break; - case AVCOL_SPC_BT470BG: - case AVCOL_SPC_SMPTE170M: - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_601_4; - break; - case AVCOL_SPC_BT709: - colormatrix = kCVImageBufferYCbCrMatrix_ITU_R_709_2; - break; - case AVCOL_SPC_SMPTE240M: - colormatrix = kCVImageBufferYCbCrMatrix_SMPTE_240M_1995; - break; - case AVCOL_SPC_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); - } + colormatrix = av_map_videotoolbox_color_matrix_from_av(src->colorspace); + if (!colormatrix && src->colorspace != AVCOL_SPC_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color space %s is not supported.\n", av_color_space_name(src->colorspace)); - switch (src->color_primaries) { - case AVCOL_PRI_BT2020: - if (__builtin_available(macOS 10.11, *)) - colorpri = kCVImageBufferColorPrimaries_ITU_R_2020; - else - colorpri = CFSTR("ITU_R_2020"); - break; - case AVCOL_PRI_BT709: - colorpri = kCVImageBufferColorPrimaries_ITU_R_709_2; - break; - case AVCOL_PRI_SMPTE170M: - colorpri = kCVImageBufferColorPrimaries_SMPTE_C; - break; - case AVCOL_PRI_BT470BG: - colorpri = kCVImageBufferColorPrimaries_EBU_3213; - break; - case AVCOL_PRI_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); - } + colorpri = av_map_videotoolbox_color_primaries_from_av(src->color_primaries); + if (!colorpri && src->color_primaries != AVCOL_PRI_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color primaries %s is not supported.\n", av_color_primaries_name(src->color_primaries)); - switch (src->color_trc) { - case AVCOL_TRC_SMPTE2084: - if (__builtin_available(macOS 10.13, *)) - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ; - else - colortrc = CFSTR("SMPTE_ST_2084_PQ"); - break; - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - if (__builtin_available(macOS 10.11, *)) - colortrc = kCVImageBufferTransferFunction_ITU_R_2020; - else - colortrc = CFSTR("ITU_R_2020"); - break; - case AVCOL_TRC_BT709: - colortrc = kCVImageBufferTransferFunction_ITU_R_709_2; - break; - case AVCOL_TRC_SMPTE240M: - colortrc = kCVImageBufferTransferFunction_SMPTE_240M_1995; - break; - case AVCOL_TRC_SMPTE428: - if (__builtin_available(macOS 10.12, *)) - colortrc = kCVImageBufferTransferFunction_SMPTE_ST_428_1; - else - colortrc = CFSTR("SMPTE_ST_428_1"); - break; - case AVCOL_TRC_ARIB_STD_B67: - if (__builtin_available(macOS 10.13, *)) - colortrc = kCVImageBufferTransferFunction_ITU_R_2100_HLG; - else - colortrc = CFSTR("ITU_R_2100_HLG"); - break; - case AVCOL_TRC_GAMMA22: + colortrc = av_map_videotoolbox_color_trc_from_av(src->color_trc); + if (!colortrc && src->color_trc != AVCOL_TRC_UNSPECIFIED) + av_log(log_ctx, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); + + if (src->color_trc == AVCOL_TRC_GAMMA22) gamma = 2.2; - colortrc = kCVImageBufferTransferFunction_UseGamma; - break; - case AVCOL_TRC_GAMMA28: + else if (src->color_trc == AVCOL_TRC_GAMMA28) gamma = 2.8; - colortrc = kCVImageBufferTransferFunction_UseGamma; - break; - case AVCOL_TRC_UNSPECIFIED: - break; - default: - av_log(hwfc, AV_LOG_WARNING, "Color transfer function %s is not supported.\n", av_color_transfer_name(src->color_trc)); - } if (colormatrix) { CVBufferSetAttachment( @@ -498,22 +567,28 @@ static int vt_pixbuf_set_colorspace(AVHWFramesContext *hwfc, return 0; } -static int vt_pixbuf_set_attachments(AVHWFramesContext *hwfc, +static int vt_pixbuf_set_attachments(void *log_ctx, CVPixelBufferRef pixbuf, const AVFrame *src) { int ret; - ret = vt_pixbuf_set_par(hwfc, pixbuf, src); + ret = vt_pixbuf_set_par(log_ctx, pixbuf, src); if (ret < 0) return ret; - ret = vt_pixbuf_set_colorspace(hwfc, pixbuf, src); + ret = vt_pixbuf_set_colorspace(log_ctx, pixbuf, src); if (ret < 0) return ret; - ret = vt_pixbuf_set_chromaloc(hwfc, pixbuf, src); + ret = vt_pixbuf_set_chromaloc(log_ctx, pixbuf, src); if (ret < 0) return ret; return 0; } +int av_vt_pixbuf_set_attachments(void *log_ctx, + CVPixelBufferRef pixbuf, const AVFrame *src) +{ + return vt_pixbuf_set_attachments(log_ctx, pixbuf, src); +} + static int vt_map_frame(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags) { @@ -636,6 +711,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) { @@ -661,6 +760,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_videotoolbox.h b/libavutil/hwcontext_videotoolbox.h index 62cde07c51..b6bdcf243d 100644 --- a/libavutil/hwcontext_videotoolbox.h +++ b/libavutil/hwcontext_videotoolbox.h @@ -60,4 +60,36 @@ uint32_t av_map_videotoolbox_format_from_pixfmt(enum AVPixelFormat pix_fmt); */ uint32_t av_map_videotoolbox_format_from_pixfmt2(enum AVPixelFormat pix_fmt, bool full_range); +/** + * Convert an AVChromaLocation to a VideoToolbox/CoreVideo chroma location string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_chroma_loc_from_av(enum AVChromaLocation loc); + +/** + * Convert an AVColorSpace to a VideoToolbox/CoreVideo color matrix string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_matrix_from_av(enum AVColorSpace space); + +/** + * Convert an AVColorPrimaries to a VideoToolbox/CoreVideo color primaries string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_primaries_from_av(enum AVColorPrimaries pri); + +/** + * Convert an AVColorTransferCharacteristic to a VideoToolbox/CoreVideo color transfer + * function string. + * Returns 0 if no known equivalent was found. + */ +CFStringRef av_map_videotoolbox_color_trc_from_av(enum AVColorTransferCharacteristic trc); + +/** + * Update a CVPixelBufferRef's metadata to based on an AVFrame. + * Returns 0 if no known equivalent was found. + */ +int av_vt_pixbuf_set_attachments(void *log_ctx, + CVPixelBufferRef pixbuf, const struct AVFrame *src); + #endif /* AVUTIL_HWCONTEXT_VIDEOTOOLBOX_H */ diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c index 2c3216857a..60a6cf6a91 100644 --- a/libavutil/hwcontext_vulkan.c +++ b/libavutil/hwcontext_vulkan.c @@ -17,23 +17,31 @@ */ #define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS + +#ifdef _WIN32 +#include /* Included to prevent conflicts with CreateSemaphore */ +#include +#include "compat/w32dlfcn.h" +#else +#include +#endif + +#include #include "config.h" #include "pixdesc.h" #include "avstring.h" #include "imgutils.h" #include "hwcontext.h" +#include "avassert.h" #include "hwcontext_internal.h" #include "hwcontext_vulkan.h" -#ifdef _WIN32 -#include "compat/w32dlfcn.h" -#else -#include -#endif +#include "vulkan.h" +#include "vulkan_loader.h" #if CONFIG_LIBDRM -#include #include #include #include "hwcontext_drm.h" @@ -49,126 +57,6 @@ #define CHECK_CU(x) FF_CUDA_CHECK_DL(cuda_cu, cu, x) #endif -enum VulkanExtensions { - EXT_EXTERNAL_DMABUF_MEMORY = 1 << 0, /* VK_EXT_external_memory_dma_buf */ - EXT_DRM_MODIFIER_FLAGS = 1 << 1, /* VK_EXT_image_drm_format_modifier */ - EXT_EXTERNAL_FD_MEMORY = 1 << 2, /* VK_KHR_external_memory_fd */ - EXT_EXTERNAL_FD_SEM = 1 << 3, /* VK_KHR_external_semaphore_fd */ - EXT_EXTERNAL_HOST_MEMORY = 1 << 4, /* VK_EXT_external_memory_host */ - EXT_PUSH_DESCRIPTORS = 1 << 5, /* VK_KHR_push_descriptor */ - EXT_DEBUG_UTILS = 1 << 6, /* VK_EXT_debug_utils */ - - EXT_NO_FLAG = 1 << 31, -}; - -#define FN_LIST(MACRO) \ - /* Instance */ \ - MACRO(0, 0, EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ - MACRO(0, 0, EXT_NO_FLAG, CreateInstance) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyInstance) \ - \ - /* Debug */ \ - MACRO(1, 0, EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ - \ - /* Device */ \ - MACRO(1, 0, EXT_NO_FLAG, GetDeviceProcAddr) \ - MACRO(1, 0, EXT_NO_FLAG, CreateDevice) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFeatures) \ - MACRO(1, 0, EXT_NO_FLAG, DestroyDevice) \ - \ - MACRO(1, 0, EXT_NO_FLAG, EnumeratePhysicalDevices) \ - MACRO(1, 0, EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ - \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ - MACRO(1, 0, EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ - \ - /* Command pool */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateCommandPool) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyCommandPool) \ - \ - /* Command buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, AllocateCommandBuffers) \ - MACRO(1, 1, EXT_NO_FLAG, BeginCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, EndCommandBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, FreeCommandBuffers) \ - \ - /* Queue */ \ - MACRO(1, 1, EXT_NO_FLAG, GetDeviceQueue) \ - MACRO(1, 1, EXT_NO_FLAG, QueueSubmit) \ - \ - /* Fences */ \ - MACRO(1, 1, EXT_NO_FLAG, CreateFence) \ - MACRO(1, 1, EXT_NO_FLAG, WaitForFences) \ - MACRO(1, 1, EXT_NO_FLAG, ResetFences) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyFence) \ - \ - /* Semaphores */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, CreateSemaphore) \ - MACRO(1, 1, EXT_NO_FLAG, DestroySemaphore) \ - \ - /* Memory */ \ - MACRO(1, 1, EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ - MACRO(1, 1, EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ - MACRO(1, 1, EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, AllocateMemory) \ - MACRO(1, 1, EXT_NO_FLAG, MapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FlushMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ - MACRO(1, 1, EXT_NO_FLAG, UnmapMemory) \ - MACRO(1, 1, EXT_NO_FLAG, FreeMemory) \ - \ - /* Commands */ \ - MACRO(1, 1, EXT_NO_FLAG, CmdPipelineBarrier) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyBufferToImage) \ - MACRO(1, 1, EXT_NO_FLAG, CmdCopyImageToBuffer) \ - \ - /* Buffer */ \ - MACRO(1, 1, EXT_NO_FLAG, GetBufferMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateBuffer) \ - MACRO(1, 1, EXT_NO_FLAG, BindBufferMemory) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyBuffer) \ - \ - /* Image */ \ - MACRO(1, 1, EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageMemoryRequirements2) \ - MACRO(1, 1, EXT_NO_FLAG, CreateImage) \ - MACRO(1, 1, EXT_NO_FLAG, BindImageMemory2) \ - MACRO(1, 1, EXT_NO_FLAG, GetImageSubresourceLayout) \ - MACRO(1, 1, EXT_NO_FLAG, DestroyImage) - -#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ - PFN_vk##name name; - -typedef struct VulkanFunctions { - FN_LIST(PFN_DEF) -} VulkanFunctions; - -#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \ - { \ - req_inst, \ - req_dev, \ - offsetof(VulkanFunctions, name), \ - ext_flag, \ - { "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \ - }, - -typedef struct VulkanFunctionsLoadInfo { - int req_inst; - int req_dev; - size_t struct_offset; - enum VulkanExtensions ext_flag; - const char *names[3]; -} VulkanFunctionsLoadInfo; - -static const VulkanFunctionsLoadInfo vk_load_info[] = { - FN_LIST(PFN_LOAD_INFO) -}; - typedef struct VulkanQueueCtx { VkFence fence; VkQueue queue; @@ -191,28 +79,38 @@ typedef struct VulkanExecCtx { typedef struct VulkanDevicePriv { /* Vulkan library and loader functions */ void *libvulkan; - VulkanFunctions vkfn; + FFVulkanFunctions vkfn; /* Properties */ VkPhysicalDeviceProperties2 props; VkPhysicalDeviceMemoryProperties mprops; VkPhysicalDeviceExternalMemoryHostPropertiesEXT hprops; + /* Features */ + VkPhysicalDeviceVulkan11Features device_features_1_1; + VkPhysicalDeviceVulkan12Features device_features_1_2; + /* Queues */ - uint32_t qfs[3]; + uint32_t qfs[5]; int num_qfs; /* Debug callback */ VkDebugUtilsMessengerEXT debug_ctx; /* Extensions */ - enum VulkanExtensions extensions; + FFVulkanExtensions extensions; /* Settings */ int use_linear_images; + /* Option to allocate all image planes in a single allocation */ + int contiguous_planes; + /* Nvidia */ int dev_is_nvidia; + + /* Intel */ + int dev_is_intel; } VulkanDevicePriv; typedef struct VulkanFramesPriv { @@ -222,6 +120,9 @@ typedef struct VulkanFramesPriv { /* Image transfers */ VulkanExecCtx upload_ctx; VulkanExecCtx download_ctx; + + /* Modifier info list to free at uninit */ + VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; } VulkanFramesPriv; typedef struct AVVkFrameInternal { @@ -233,24 +134,13 @@ typedef struct AVVkFrameInternal { CUmipmappedArray cu_mma[AV_NUM_DATA_POINTERS]; CUarray cu_array[AV_NUM_DATA_POINTERS]; CUexternalSemaphore cu_sem[AV_NUM_DATA_POINTERS]; +#ifdef _WIN32 + HANDLE ext_mem_handle[AV_NUM_DATA_POINTERS]; + HANDLE ext_sem_handle[AV_NUM_DATA_POINTERS]; +#endif #endif } AVVkFrameInternal; -#define GET_QUEUE_COUNT(hwctx, graph, comp, tx) ( \ - graph ? hwctx->nb_graphics_queues : \ - comp ? (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues) : \ - tx ? (hwctx->nb_tx_queues ? hwctx->nb_tx_queues : \ - (hwctx->nb_comp_queues ? \ - hwctx->nb_comp_queues : hwctx->nb_graphics_queues)) : \ - 0 \ -) - -#define DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ - VK_IMAGE_USAGE_STORAGE_BIT | \ - VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ - VK_IMAGE_USAGE_TRANSFER_DST_BIT) - #define ADD_VAL_TO_LIST(list, count, val) \ do { \ list = av_realloc_array(list, sizeof(*list), ++count); \ @@ -265,6 +155,13 @@ typedef struct AVVkFrameInternal { } \ } while(0) +#define RELEASE_PROPS(props, count) \ + if (props) { \ + for (int i = 0; i < count; i++) \ + av_free((void *)((props)[i])); \ + av_free((void *)props); \ + } + static const struct { enum AVPixelFormat pixfmt; const VkFormat vkfmts[4]; @@ -346,12 +243,37 @@ const VkFormat *av_vkfmt_from_pixfmt(enum AVPixelFormat p) return NULL; } +static const void *vk_find_struct(const void *chain, VkStructureType stype) +{ + const VkBaseInStructure *in = chain; + while (in) { + if (in->sType == stype) + return in; + + in = in->pNext; + } + + return NULL; +} + +static void vk_link_struct(void *chain, void *in) +{ + VkBaseOutStructure *out = chain; + if (!in) + return; + + while (out->pNext) + out = out->pNext; + + out->pNext = in; +} + static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, int linear) { AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *priv = dev_ctx->internal->priv; - VulkanFunctions *vk = &priv->vkfn; + FFVulkanFunctions *vk = &priv->vkfn; const VkFormat *fmt = av_vkfmt_from_pixfmt(p); int planes = av_pix_fmt_count_planes(p); @@ -366,7 +288,7 @@ static int pixfmt_is_supported(AVHWDeviceContext *dev_ctx, enum AVPixelFormat p, vk->GetPhysicalDeviceFormatProperties2(hwctx->phys_dev, fmt[i], &prop); flags = linear ? prop.formatProperties.linearTilingFeatures : prop.formatProperties.optimalTilingFeatures; - if (!(flags & DEFAULT_USAGE_FLAGS)) + if (!(flags & FF_VK_DEFAULT_USAGE_FLAGS)) return 0; } @@ -407,50 +329,9 @@ static int load_libvulkan(AVHWDeviceContext *ctx) return 0; } -static int load_functions(AVHWDeviceContext *ctx, int has_inst, int has_dev) -{ - AVVulkanDeviceContext *hwctx = ctx->hwctx; - VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; - - for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { - const VulkanFunctionsLoadInfo *load = &vk_load_info[i]; - PFN_vkVoidFunction fn; - - if (load->req_dev && !has_dev) - continue; - if (load->req_inst && !has_inst) - continue; - - for (int j = 0; j < FF_ARRAY_ELEMS(load->names); j++) { - const char *name = load->names[j]; - - if (load->req_dev) - fn = vk->GetDeviceProcAddr(hwctx->act_dev, name); - else if (load->req_inst) - fn = hwctx->get_proc_addr(hwctx->inst, name); - else - fn = hwctx->get_proc_addr(NULL, name); - - if (fn) - break; - } - - if (!fn && ((p->extensions &~ EXT_NO_FLAG) & load->ext_flag)) { - av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated" - "as supported, but got NULL function pointer!\n", load->names[0]); - return AVERROR_EXTERNAL; - } - - *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn; - } - - return 0; -} - typedef struct VulkanOptExtension { const char *name; - enum VulkanExtensions flag; + FFVulkanExtensions flag; } VulkanOptExtension; static const VulkanOptExtension optional_instance_exts[] = { @@ -458,13 +339,29 @@ static const VulkanOptExtension optional_instance_exts[] = { }; static const VulkanOptExtension optional_device_exts[] = { - { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_MEMORY, }, - { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, EXT_EXTERNAL_DMABUF_MEMORY, }, - { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, EXT_DRM_MODIFIER_FLAGS, }, - { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, EXT_EXTERNAL_FD_SEM, }, - { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, EXT_EXTERNAL_HOST_MEMORY, }, - { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, EXT_PUSH_DESCRIPTORS, }, - { VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, EXT_NO_FLAG, }, + /* Misc or required by other extensions */ + { VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + + /* Imports/exports */ + { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, + { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY }, + { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, + { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, + { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, +#ifdef _WIN32 + { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, +#endif + + /* Video encoding/decoding */ + { VK_KHR_VIDEO_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_DECODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_KHR_VIDEO_ENCODE_QUEUE_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H264_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, + { VK_EXT_VIDEO_DECODE_H265_EXTENSION_NAME, FF_VK_EXT_NO_FLAG }, }; /* Converts return values to strings */ @@ -537,7 +434,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, const char *tstr; const char **extension_names = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; int err = 0, found, extensions_found = 0; @@ -599,7 +496,7 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, if (!found) continue; - av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, tstr); + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); p->extensions |= optional_exts[i].flag; ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); } @@ -614,9 +511,9 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, } } if (found) { - av_log(ctx, AV_LOG_VERBOSE, "Using %s extension \"%s\"\n", mod, tstr); + av_log(ctx, AV_LOG_VERBOSE, "Using %s extension %s\n", mod, tstr); ADD_VAL_TO_LIST(extension_names, extensions_found, tstr); - p->extensions |= EXT_DEBUG_UTILS; + p->extensions |= FF_VK_EXT_DEBUG_UTILS; } else { av_log(ctx, AV_LOG_ERROR, "Debug extension \"%s\" not found!\n", tstr); @@ -654,29 +551,133 @@ static int check_extensions(AVHWDeviceContext *ctx, int dev, AVDictionary *opts, return 0; fail: - if (extension_names) - for (int i = 0; i < extensions_found; i++) - av_free((void *)extension_names[i]); - av_free(extension_names); + RELEASE_PROPS(extension_names, extensions_found); av_free(user_exts_str); av_free(sup_ext); return err; } +static int check_validation_layers(AVHWDeviceContext *ctx, AVDictionary *opts, + const char * const **dst, uint32_t *num, + int *debug_mode) +{ + static const char default_layer[] = { "VK_LAYER_KHRONOS_validation" }; + + int found = 0, err = 0; + VulkanDevicePriv *priv = ctx->internal->priv; + FFVulkanFunctions *vk = &priv->vkfn; + + uint32_t sup_layer_count; + VkLayerProperties *sup_layers; + + AVDictionaryEntry *user_layers; + char *user_layers_str = NULL; + char *save, *token; + + const char **enabled_layers = NULL; + uint32_t enabled_layers_count = 0; + + AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); + int debug = debug_opt && strtol(debug_opt->value, NULL, 10); + + /* If `debug=0`, enable no layers at all. */ + if (debug_opt && !debug) + return 0; + + vk->EnumerateInstanceLayerProperties(&sup_layer_count, NULL); + sup_layers = av_malloc_array(sup_layer_count, sizeof(VkLayerProperties)); + if (!sup_layers) + return AVERROR(ENOMEM); + vk->EnumerateInstanceLayerProperties(&sup_layer_count, sup_layers); + + av_log(ctx, AV_LOG_VERBOSE, "Supported validation layers:\n"); + for (int i = 0; i < sup_layer_count; i++) + av_log(ctx, AV_LOG_VERBOSE, "\t%s\n", sup_layers[i].layerName); + + /* If `debug=1` is specified, enable the standard validation layer extension */ + if (debug) { + *debug_mode = debug; + for (int i = 0; i < sup_layer_count; i++) { + if (!strcmp(default_layer, sup_layers[i].layerName)) { + found = 1; + av_log(ctx, AV_LOG_VERBOSE, "Default validation layer %s is enabled\n", + default_layer); + ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, default_layer); + break; + } + } + } + + user_layers = av_dict_get(opts, "validation_layers", NULL, 0); + if (!user_layers) + goto end; + + user_layers_str = av_strdup(user_layers->value); + if (!user_layers_str) { + err = AVERROR(ENOMEM); + goto fail; + } + + token = av_strtok(user_layers_str, "+", &save); + while (token) { + found = 0; + if (!strcmp(default_layer, token)) { + if (debug) { + /* if the `debug=1`, default_layer is enabled, skip here */ + token = av_strtok(NULL, "+", &save); + continue; + } else { + /* if the `debug=0`, enable debug mode to load its callback properly */ + *debug_mode = debug; + } + } + for (int j = 0; j < sup_layer_count; j++) { + if (!strcmp(token, sup_layers[j].layerName)) { + found = 1; + break; + } + } + if (found) { + av_log(ctx, AV_LOG_VERBOSE, "Requested Validation Layer: %s\n", token); + ADD_VAL_TO_LIST(enabled_layers, enabled_layers_count, token); + } else { + av_log(ctx, AV_LOG_ERROR, + "Validation Layer \"%s\" not support.\n", token); + err = AVERROR(EINVAL); + goto fail; + } + token = av_strtok(NULL, "+", &save); + } + + av_free(user_layers_str); + +end: + av_free(sup_layers); + + *dst = enabled_layers; + *num = enabled_layers_count; + + return 0; + +fail: + RELEASE_PROPS(enabled_layers, enabled_layers_count); + av_free(sup_layers); + av_free(user_layers_str); + return err; +} + /* Creates a VkInstance */ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) { - int err = 0; + int err = 0, debug_mode = 0; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - AVDictionaryEntry *debug_opt = av_dict_get(opts, "debug", NULL, 0); - const int debug_mode = debug_opt && strtol(debug_opt->value, NULL, 10); VkApplicationInfo application_info = { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pEngineName = "libavutil", - .apiVersion = VK_API_VERSION_1_1, + .apiVersion = VK_API_VERSION_1_2, .engineVersion = VK_MAKE_VERSION(LIBAVUTIL_VERSION_MAJOR, LIBAVUTIL_VERSION_MINOR, LIBAVUTIL_VERSION_MICRO), @@ -692,23 +693,24 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) return err; } - err = load_functions(ctx, 0, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 0, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance enumeration functions!\n"); return err; } + err = check_validation_layers(ctx, opts, &inst_props.ppEnabledLayerNames, + &inst_props.enabledLayerCount, &debug_mode); + if (err) + goto fail; + /* Check for present/missing extensions */ err = check_extensions(ctx, 0, opts, &inst_props.ppEnabledExtensionNames, &inst_props.enabledExtensionCount, debug_mode); + hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; + hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; if (err < 0) - return err; - - if (debug_mode) { - static const char *layers[] = { "VK_LAYER_KHRONOS_validation" }; - inst_props.ppEnabledLayerNames = layers; - inst_props.enabledLayerCount = FF_ARRAY_ELEMS(layers); - } + goto fail; /* Try to create the instance */ ret = vk->CreateInstance(&inst_props, hwctx->alloc, &hwctx->inst); @@ -717,16 +719,14 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Instance creation failure: %s\n", vk_ret2str(ret)); - for (int i = 0; i < inst_props.enabledExtensionCount; i++) - av_free((void *)inst_props.ppEnabledExtensionNames[i]); - av_free((void *)inst_props.ppEnabledExtensionNames); - return AVERROR_EXTERNAL; + err = AVERROR_EXTERNAL; + goto fail; } - err = load_functions(ctx, 1, 0); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 0); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load instance functions!\n"); - return err; + goto fail; } if (debug_mode) { @@ -747,10 +747,11 @@ static int create_instance(AVHWDeviceContext *ctx, AVDictionary *opts) hwctx->alloc, &p->debug_ctx); } - hwctx->enabled_inst_extensions = inst_props.ppEnabledExtensionNames; - hwctx->nb_enabled_inst_extensions = inst_props.enabledExtensionCount; + err = 0; - return 0; +fail: + RELEASE_PROPS(inst_props.ppEnabledLayerNames, inst_props.enabledLayerCount); + return err; } typedef struct VulkanDeviceSelection { @@ -780,7 +781,7 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) uint32_t num; VkResult ret; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkPhysicalDevice *devices = NULL; VkPhysicalDeviceIDProperties *idp = NULL; VkPhysicalDeviceProperties2 *prop = NULL; @@ -887,8 +888,13 @@ static int find_device(AVHWDeviceContext *ctx, VulkanDeviceSelection *select) } end: - if (choice > -1) + if (choice > -1) { + av_log(ctx, AV_LOG_VERBOSE, "Device %d selected: %s (%s) (0x%x)\n", + choice, prop[choice].properties.deviceName, + vk_dev_type(prop[choice].properties.deviceType), + prop[choice].properties.deviceID); hwctx->phys_dev = devices[choice]; + } av_free(devices); av_free(prop); @@ -897,16 +903,39 @@ end: return err; } -static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) +/* Picks the least used qf with the fewest unneeded flags, or -1 if none found */ +static inline int pick_queue_family(VkQueueFamilyProperties *qf, uint32_t num_qf, + VkQueueFlagBits flags) +{ + int index = -1; + uint32_t min_score = UINT32_MAX; + + for (int i = 0; i < num_qf; i++) { + const VkQueueFlagBits qflags = qf[i].queueFlags; + if (qflags & flags) { + uint32_t score = av_popcount(qflags) + qf[i].timestampValidBits; + if (score < min_score) { + index = i; + min_score = score; + } + } + } + + if (index > -1) + qf[index].timestampValidBits++; + + return index; +} + +static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) { uint32_t num; float *weights; - VkQueueFamilyProperties *qs = NULL; + VkQueueFamilyProperties *qf = NULL; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - int graph_index = -1, comp_index = -1, tx_index = -1; - VkDeviceQueueCreateInfo *pc = (VkDeviceQueueCreateInfo *)cd->pQueueCreateInfos; + int graph_index, comp_index, tx_index, enc_index, dec_index; /* First get the number of queue families */ vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, NULL); @@ -916,81 +945,120 @@ static int search_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd) } /* Then allocate memory */ - qs = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); - if (!qs) + qf = av_malloc_array(num, sizeof(VkQueueFamilyProperties)); + if (!qf) return AVERROR(ENOMEM); /* Finally retrieve the queue families */ - vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qs); + vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &num, qf); -#define SEARCH_FLAGS(expr, out) \ - for (int i = 0; i < num; i++) { \ - const VkQueueFlagBits flags = qs[i].queueFlags; \ - if (expr) { \ - out = i; \ - break; \ + av_log(ctx, AV_LOG_VERBOSE, "Queue families:\n"); + for (int i = 0; i < num; i++) { + av_log(ctx, AV_LOG_VERBOSE, " %i:%s%s%s%s%s%s%s (queues: %i)\n", i, + ((qf[i].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? " graphics" : "", + ((qf[i].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? " compute" : "", + ((qf[i].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? " transfer" : "", + ((qf[i].queueFlags) & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) ? " encode" : "", + ((qf[i].queueFlags) & VK_QUEUE_VIDEO_DECODE_BIT_KHR) ? " decode" : "", + ((qf[i].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? " sparse" : "", + ((qf[i].queueFlags) & VK_QUEUE_PROTECTED_BIT) ? " protected" : "", + qf[i].queueCount); + + /* We use this field to keep a score of how many times we've used that + * queue family in order to make better choices. */ + qf[i].timestampValidBits = 0; + } + + /* Pick each queue family to use */ + graph_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); + comp_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); + tx_index = pick_queue_family(qf, num, VK_QUEUE_TRANSFER_BIT); + enc_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_ENCODE_BIT_KHR); + dec_index = pick_queue_family(qf, num, VK_QUEUE_VIDEO_DECODE_BIT_KHR); + + /* Signalling the transfer capabilities on a queue family is optional */ + if (tx_index < 0) { + tx_index = pick_queue_family(qf, num, VK_QUEUE_COMPUTE_BIT); + if (tx_index < 0) + tx_index = pick_queue_family(qf, num, VK_QUEUE_GRAPHICS_BIT); + } + + hwctx->queue_family_index = -1; + hwctx->queue_family_comp_index = -1; + hwctx->queue_family_tx_index = -1; + hwctx->queue_family_encode_index = -1; + hwctx->queue_family_decode_index = -1; + +#define SETUP_QUEUE(qf_idx) \ + if (qf_idx > -1) { \ + int fidx = qf_idx; \ + int qc = qf[fidx].queueCount; \ + VkDeviceQueueCreateInfo *pc; \ + \ + if (fidx == graph_index) { \ + hwctx->queue_family_index = fidx; \ + hwctx->nb_graphics_queues = qc; \ + graph_index = -1; \ } \ + if (fidx == comp_index) { \ + hwctx->queue_family_comp_index = fidx; \ + hwctx->nb_comp_queues = qc; \ + comp_index = -1; \ + } \ + if (fidx == tx_index) { \ + hwctx->queue_family_tx_index = fidx; \ + hwctx->nb_tx_queues = qc; \ + tx_index = -1; \ + } \ + if (fidx == enc_index) { \ + hwctx->queue_family_encode_index = fidx; \ + hwctx->nb_encode_queues = qc; \ + enc_index = -1; \ + } \ + if (fidx == dec_index) { \ + hwctx->queue_family_decode_index = fidx; \ + hwctx->nb_decode_queues = qc; \ + dec_index = -1; \ + } \ + \ + pc = av_realloc((void *)cd->pQueueCreateInfos, \ + sizeof(*pc) * (cd->queueCreateInfoCount + 1)); \ + if (!pc) { \ + av_free(qf); \ + return AVERROR(ENOMEM); \ + } \ + cd->pQueueCreateInfos = pc; \ + pc = &pc[cd->queueCreateInfoCount]; \ + \ + weights = av_malloc(qc * sizeof(float)); \ + if (!weights) { \ + av_free(qf); \ + return AVERROR(ENOMEM); \ + } \ + \ + memset(pc, 0, sizeof(*pc)); \ + pc->sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; \ + pc->queueFamilyIndex = fidx; \ + pc->queueCount = qc; \ + pc->pQueuePriorities = weights; \ + \ + for (int i = 0; i < qc; i++) \ + weights[i] = 1.0f / qc; \ + \ + cd->queueCreateInfoCount++; \ } - SEARCH_FLAGS(flags & VK_QUEUE_GRAPHICS_BIT, graph_index) - - SEARCH_FLAGS((flags & VK_QUEUE_COMPUTE_BIT) && (i != graph_index), - comp_index) - - SEARCH_FLAGS((flags & VK_QUEUE_TRANSFER_BIT) && (i != graph_index) && - (i != comp_index), tx_index) - -#undef SEARCH_FLAGS -#define ADD_QUEUE(fidx, graph, comp, tx) \ - av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (total queues: %i) for %s%s%s\n", \ - fidx, qs[fidx].queueCount, graph ? "graphics " : "", \ - comp ? "compute " : "", tx ? "transfers " : ""); \ - av_log(ctx, AV_LOG_VERBOSE, " QF %i flags: %s%s%s%s\n", fidx, \ - ((qs[fidx].queueFlags) & VK_QUEUE_GRAPHICS_BIT) ? "(graphics) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_COMPUTE_BIT) ? "(compute) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_TRANSFER_BIT) ? "(transfers) " : "", \ - ((qs[fidx].queueFlags) & VK_QUEUE_SPARSE_BINDING_BIT) ? "(sparse) " : ""); \ - pc[cd->queueCreateInfoCount].queueFamilyIndex = fidx; \ - pc[cd->queueCreateInfoCount].queueCount = qs[fidx].queueCount; \ - weights = av_malloc(qs[fidx].queueCount * sizeof(float)); \ - pc[cd->queueCreateInfoCount].pQueuePriorities = weights; \ - if (!weights) \ - goto fail; \ - for (int i = 0; i < qs[fidx].queueCount; i++) \ - weights[i] = 1.0f; \ - cd->queueCreateInfoCount++; - - ADD_QUEUE(graph_index, 1, comp_index < 0, tx_index < 0 && comp_index < 0) - hwctx->queue_family_index = graph_index; - hwctx->queue_family_comp_index = graph_index; - hwctx->queue_family_tx_index = graph_index; - hwctx->nb_graphics_queues = qs[graph_index].queueCount; - - if (comp_index != -1) { - ADD_QUEUE(comp_index, 0, 1, tx_index < 0) - hwctx->queue_family_tx_index = comp_index; - hwctx->queue_family_comp_index = comp_index; - hwctx->nb_comp_queues = qs[comp_index].queueCount; - } - - if (tx_index != -1) { - ADD_QUEUE(tx_index, 0, 0, 1) - hwctx->queue_family_tx_index = tx_index; - hwctx->nb_tx_queues = qs[tx_index].queueCount; - } + SETUP_QUEUE(graph_index) + SETUP_QUEUE(comp_index) + SETUP_QUEUE(tx_index) + SETUP_QUEUE(enc_index) + SETUP_QUEUE(dec_index) #undef ADD_QUEUE - av_free(qs); + + av_free(qf); return 0; - -fail: - av_freep(&pc[0].pQueuePriorities); - av_freep(&pc[1].pQueuePriorities); - av_freep(&pc[2].pQueuePriorities); - av_free(qs); - - return AVERROR(ENOMEM); } static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, @@ -999,7 +1067,7 @@ static int create_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, VkResult ret; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandPoolCreateInfo cqueue_create = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -1055,7 +1123,7 @@ static void free_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) { AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; if (cmd->queues) { for (int i = 0; i < cmd->nb_queues; i++) { @@ -1108,7 +1176,7 @@ static int wait_start_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkCommandBufferBeginInfo cmd_start = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, @@ -1176,12 +1244,12 @@ err: } static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, - VkSubmitInfo *s_info, int synchronous) + VkSubmitInfo *s_info, AVVkFrame *f, int synchronous) { VkResult ret; VulkanQueueCtx *q = &cmd->queues[cmd->cur_queue_idx]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ret = vk->EndCommandBuffer(cmd->bufs[cmd->cur_queue_idx]); if (ret != VK_SUCCESS) { @@ -1196,10 +1264,16 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, ret = vk->QueueSubmit(q->queue, 1, s_info, q->fence); if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Queue submission failure: %s\n", + vk_ret2str(ret)); unref_exec_ctx_deps(hwfc, cmd); return AVERROR_EXTERNAL; } + if (f) + for (int i = 0; i < s_info->signalSemaphoreCount; i++) + f->sem_value[i]++; + q->was_synchronous = synchronous; if (synchronous) { @@ -1217,27 +1291,24 @@ static int submit_exec_ctx(AVHWFramesContext *hwfc, VulkanExecCtx *cmd, static void vulkan_device_free(AVHWDeviceContext *ctx) { VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); + if (hwctx->act_dev) + vk->DestroyDevice(hwctx->act_dev, hwctx->alloc); if (p->debug_ctx) vk->DestroyDebugUtilsMessengerEXT(hwctx->inst, p->debug_ctx, hwctx->alloc); - vk->DestroyInstance(hwctx->inst, hwctx->alloc); + if (hwctx->inst) + vk->DestroyInstance(hwctx->inst, hwctx->alloc); if (p->libvulkan) dlclose(p->libvulkan); - for (int i = 0; i < hwctx->nb_enabled_inst_extensions; i++) - av_free((void *)hwctx->enabled_inst_extensions[i]); - av_free((void *)hwctx->enabled_inst_extensions); - - for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) - av_free((void *)hwctx->enabled_dev_extensions[i]); - av_free((void *)hwctx->enabled_dev_extensions); + RELEASE_PROPS(hwctx->enabled_inst_extensions, hwctx->nb_enabled_inst_extensions); + RELEASE_PROPS(hwctx->enabled_dev_extensions, hwctx->nb_enabled_dev_extensions); } static int vulkan_device_create_internal(AVHWDeviceContext *ctx, @@ -1248,23 +1319,30 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, VkResult ret; AVDictionaryEntry *opt_d; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; - VkPhysicalDeviceFeatures dev_features = { 0 }; - VkDeviceQueueCreateInfo queue_create_info[3] = { - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, - { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, }, + VkPhysicalDeviceVulkan12Features dev_features_1_2 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, + }; + VkPhysicalDeviceVulkan11Features dev_features_1_1 = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, + .pNext = &dev_features_1_2, + }; + VkPhysicalDeviceFeatures2 dev_features = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, + .pNext = &dev_features_1_1, }; VkDeviceCreateInfo dev_info = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = &hwctx->device_features, - .pQueueCreateInfos = queue_create_info, - .queueCreateInfoCount = 0, }; hwctx->device_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + hwctx->device_features.pNext = &p->device_features_1_1; + p->device_features_1_1.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES; + p->device_features_1_1.pNext = &p->device_features_1_2; + p->device_features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES; ctx->free = vulkan_device_free; /* Create an instance if not given one */ @@ -1275,10 +1353,10 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if ((err = find_device(ctx, dev_select))) goto end; - vk->GetPhysicalDeviceFeatures(hwctx->phys_dev, &dev_features); + vk->GetPhysicalDeviceFeatures2(hwctx->phys_dev, &dev_features); /* Try to keep in sync with libplacebo */ -#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.NAME; +#define COPY_FEATURE(DST, NAME) (DST).features.NAME = dev_features.features.NAME; COPY_FEATURE(hwctx->device_features, shaderImageGatherExtended) COPY_FEATURE(hwctx->device_features, shaderStorageImageReadWithoutFormat) COPY_FEATURE(hwctx->device_features, shaderStorageImageWriteWithoutFormat) @@ -1287,24 +1365,32 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, COPY_FEATURE(hwctx->device_features, shaderInt64) #undef COPY_FEATURE - /* Search queue family */ - if ((err = search_queue_families(ctx, &dev_info))) + /* We require timeline semaphores */ + if (!dev_features_1_2.timelineSemaphore) { + av_log(ctx, AV_LOG_ERROR, "Device does not support timeline semaphores!\n"); + err = AVERROR(ENOSYS); + goto end; + } + p->device_features_1_2.timelineSemaphore = 1; + + /* Setup queue family */ + if ((err = setup_queue_families(ctx, &dev_info))) goto end; if ((err = check_extensions(ctx, 1, opts, &dev_info.ppEnabledExtensionNames, &dev_info.enabledExtensionCount, 0))) { - av_free((void *)queue_create_info[0].pQueuePriorities); - av_free((void *)queue_create_info[1].pQueuePriorities); - av_free((void *)queue_create_info[2].pQueuePriorities); + for (int i = 0; i < dev_info.queueCreateInfoCount; i++) + av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities); + av_free((void *)dev_info.pQueueCreateInfos); goto end; } ret = vk->CreateDevice(hwctx->phys_dev, &dev_info, hwctx->alloc, &hwctx->act_dev); - av_free((void *)queue_create_info[0].pQueuePriorities); - av_free((void *)queue_create_info[1].pQueuePriorities); - av_free((void *)queue_create_info[2].pQueuePriorities); + for (int i = 0; i < dev_info.queueCreateInfoCount; i++) + av_free((void *)dev_info.pQueueCreateInfos[i].pQueuePriorities); + av_free((void *)dev_info.pQueueCreateInfos); if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Device creation failure: %s\n", @@ -1321,6 +1407,12 @@ static int vulkan_device_create_internal(AVHWDeviceContext *ctx, if (opt_d) p->use_linear_images = strtol(opt_d->value, NULL, 10); + opt_d = av_dict_get(opts, "contiguous_planes", NULL, 0); + if (opt_d) + p->contiguous_planes = strtol(opt_d->value, NULL, 10); + else + p->contiguous_planes = -1; + hwctx->enabled_dev_extensions = dev_info.ppEnabledExtensionNames; hwctx->nb_enabled_dev_extensions = dev_info.enabledExtensionCount; @@ -1334,22 +1426,21 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) uint32_t queue_num; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; + int graph_index, comp_index, tx_index, enc_index, dec_index; /* Set device extension flags */ for (int i = 0; i < hwctx->nb_enabled_dev_extensions; i++) { for (int j = 0; j < FF_ARRAY_ELEMS(optional_device_exts); j++) { if (!strcmp(hwctx->enabled_dev_extensions[i], optional_device_exts[j].name)) { - av_log(ctx, AV_LOG_VERBOSE, "Using device extension %s\n", - hwctx->enabled_dev_extensions[i]); p->extensions |= optional_device_exts[j].flag; break; } } } - err = load_functions(ctx, 1, 1); + err = ff_vk_load_functions(ctx, vk, p->extensions, 1, 1); if (err < 0) { av_log(ctx, AV_LOG_ERROR, "Unable to load functions!\n"); return err; @@ -1367,11 +1458,12 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) p->props.properties.limits.optimalBufferCopyRowPitchAlignment); av_log(ctx, AV_LOG_VERBOSE, " minMemoryMapAlignment: %"SIZE_SPECIFIER"\n", p->props.properties.limits.minMemoryMapAlignment); - if (p->extensions & EXT_EXTERNAL_HOST_MEMORY) + if (p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY) av_log(ctx, AV_LOG_VERBOSE, " minImportedHostPointerAlignment: %"PRIu64"\n", p->hprops.minImportedHostPointerAlignment); p->dev_is_nvidia = (p->props.properties.vendorID == 0x10de); + p->dev_is_intel = (p->props.properties.vendorID == 0x8086); vk->GetPhysicalDeviceQueueFamilyProperties(hwctx->phys_dev, &queue_num, NULL); if (!queue_num) { @@ -1379,27 +1471,50 @@ static int vulkan_device_init(AVHWDeviceContext *ctx) return AVERROR_EXTERNAL; } -#define CHECK_QUEUE(type, n) \ -if (n >= queue_num) { \ - av_log(ctx, AV_LOG_ERROR, "Invalid %s queue index %i (device has %i queues)!\n", \ - type, n, queue_num); \ - return AVERROR(EINVAL); \ -} + graph_index = hwctx->queue_family_index; + comp_index = hwctx->queue_family_comp_index; + tx_index = hwctx->queue_family_tx_index; + enc_index = hwctx->queue_family_encode_index; + dec_index = hwctx->queue_family_decode_index; - CHECK_QUEUE("graphics", hwctx->queue_family_index) - CHECK_QUEUE("upload", hwctx->queue_family_tx_index) - CHECK_QUEUE("compute", hwctx->queue_family_comp_index) +#define CHECK_QUEUE(type, required, fidx, ctx_qf, qc) \ + do { \ + if (ctx_qf < 0 && required) { \ + av_log(ctx, AV_LOG_ERROR, "%s queue family is required, but marked as missing" \ + " in the context!\n", type); \ + return AVERROR(EINVAL); \ + } else if (fidx < 0 || ctx_qf < 0) { \ + break; \ + } else if (ctx_qf >= queue_num) { \ + av_log(ctx, AV_LOG_ERROR, "Invalid %s family index %i (device has %i families)!\n", \ + type, ctx_qf, queue_num); \ + return AVERROR(EINVAL); \ + } \ + \ + av_log(ctx, AV_LOG_VERBOSE, "Using queue family %i (queues: %i)" \ + " for%s%s%s%s%s\n", \ + ctx_qf, qc, \ + ctx_qf == graph_index ? " graphics" : "", \ + ctx_qf == comp_index ? " compute" : "", \ + ctx_qf == tx_index ? " transfers" : "", \ + ctx_qf == enc_index ? " encode" : "", \ + ctx_qf == dec_index ? " decode" : ""); \ + graph_index = (ctx_qf == graph_index) ? -1 : graph_index; \ + comp_index = (ctx_qf == comp_index) ? -1 : comp_index; \ + tx_index = (ctx_qf == tx_index) ? -1 : tx_index; \ + enc_index = (ctx_qf == enc_index) ? -1 : enc_index; \ + dec_index = (ctx_qf == dec_index) ? -1 : dec_index; \ + p->qfs[p->num_qfs++] = ctx_qf; \ + } while (0) + + CHECK_QUEUE("graphics", 0, graph_index, hwctx->queue_family_index, hwctx->nb_graphics_queues); + CHECK_QUEUE("upload", 1, tx_index, hwctx->queue_family_tx_index, hwctx->nb_tx_queues); + CHECK_QUEUE("compute", 1, comp_index, hwctx->queue_family_comp_index, hwctx->nb_comp_queues); + CHECK_QUEUE("encode", 0, enc_index, hwctx->queue_family_encode_index, hwctx->nb_encode_queues); + CHECK_QUEUE("decode", 0, dec_index, hwctx->queue_family_decode_index, hwctx->nb_decode_queues); #undef CHECK_QUEUE - p->qfs[p->num_qfs++] = hwctx->queue_family_index; - if ((hwctx->queue_family_tx_index != hwctx->queue_family_index) && - (hwctx->queue_family_tx_index != hwctx->queue_family_comp_index)) - p->qfs[p->num_qfs++] = hwctx->queue_family_tx_index; - if ((hwctx->queue_family_comp_index != hwctx->queue_family_index) && - (hwctx->queue_family_comp_index != hwctx->queue_family_tx_index)) - p->qfs[p->num_qfs++] = hwctx->queue_family_comp_index; - /* Get device capabilities */ vk->GetPhysicalDeviceMemoryProperties(hwctx->phys_dev, &p->mprops); @@ -1546,7 +1661,7 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, VkResult ret; int index = -1; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *dev_hwctx = ctx->hwctx; VkMemoryAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, @@ -1597,8 +1712,10 @@ static int alloc_mem(AVHWDeviceContext *ctx, VkMemoryRequirements *req, return 0; } -static void vulkan_free_internal(AVVkFrameInternal *internal) +static void vulkan_free_internal(AVVkFrame *f) { + AVVkFrameInternal *internal = f->internal; + if (!internal) return; @@ -1618,13 +1735,19 @@ static void vulkan_free_internal(AVVkFrameInternal *internal) CHECK_CU(cu->cuMipmappedArrayDestroy(internal->cu_mma[i])); if (internal->ext_mem[i]) CHECK_CU(cu->cuDestroyExternalMemory(internal->ext_mem[i])); +#ifdef _WIN32 + if (internal->ext_sem_handle[i]) + CloseHandle(internal->ext_sem_handle[i]); + if (internal->ext_mem_handle[i]) + CloseHandle(internal->ext_mem_handle[i]); +#endif } av_buffer_unref(&internal->cuda_fc_ref); } #endif - av_free(internal); + av_freep(&f->internal); } static void vulkan_frame_free(void *opaque, uint8_t *data) @@ -1633,10 +1756,14 @@ static void vulkan_frame_free(void *opaque, uint8_t *data) AVHWFramesContext *hwfc = opaque; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int planes = av_pix_fmt_count_planes(hwfc->sw_format); - vulkan_free_internal(f->internal); + /* We could use vkWaitSemaphores, but the validation layer seems to have + * issues tracking command buffer execution state on uninit. */ + vk->DeviceWaitIdle(hwctx->act_dev); + + vulkan_free_internal(f); for (int i = 0; i < planes; i++) { vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); @@ -1654,10 +1781,15 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { { 0 } }; + VkMemoryRequirements cont_memory_requirements = { 0 }; + int cont_mem_size_list[AV_NUM_DATA_POINTERS] = { 0 }; + int cont_mem_size = 0; + AVVulkanDeviceContext *hwctx = ctx->hwctx; for (int i = 0; i < planes; i++) { @@ -1684,6 +1816,27 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, req.memoryRequirements.size = FFALIGN(req.memoryRequirements.size, p->props.properties.limits.minMemoryMapAlignment); + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + if (ded_req.requiresDedicatedAllocation) { + av_log(hwfc, AV_LOG_ERROR, "Cannot allocate all planes in a single allocation, " + "device requires dedicated image allocation!\n"); + return AVERROR(EINVAL); + } else if (!i) { + cont_memory_requirements = req.memoryRequirements; + } else if (cont_memory_requirements.memoryTypeBits != + req.memoryRequirements.memoryTypeBits) { + av_log(hwfc, AV_LOG_ERROR, "The memory requirements differ between plane 0 " + "and %i, cannot allocate in a single region!\n", + i); + return AVERROR(EINVAL); + } + + cont_mem_size_list[i] = FFALIGN(req.memoryRequirements.size, + req.memoryRequirements.alignment); + cont_mem_size += cont_mem_size_list[i]; + continue; + } + /* In case the implementation prefers/requires dedicated allocation */ use_ded_mem = ded_req.prefersDedicatedAllocation | ded_req.requiresDedicatedAllocation; @@ -1705,6 +1858,31 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, bind_info[i].memory = f->mem[i]; } + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + cont_memory_requirements.size = cont_mem_size; + + /* Allocate memory */ + if ((err = alloc_mem(ctx, &cont_memory_requirements, + f->tiling == VK_IMAGE_TILING_LINEAR ? + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT : + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + (void *)(((uint8_t *)alloc_pnext)), + &f->flags, &f->mem[0]))) + return err; + + f->size[0] = cont_memory_requirements.size; + + for (int i = 0, offset = 0; i < planes; i++) { + bind_info[i].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; + bind_info[i].image = f->img[i]; + bind_info[i].memory = f->mem[0]; + bind_info[i].memoryOffset = offset; + + f->offset[i] = bind_info[i].memoryOffset; + offset += cont_mem_size_list[i]; + } + } + /* Bind the allocated memory to the images */ ret = vk->BindImageMemory2(hwctx->act_dev, planes, bind_info); if (ret != VK_SUCCESS) { @@ -1718,48 +1896,68 @@ static int alloc_bind_mem(AVHWFramesContext *hwfc, AVVkFrame *f, enum PrepMode { PREP_MODE_WRITE, - PREP_MODE_RO_SHADER, PREP_MODE_EXTERNAL_EXPORT, + PREP_MODE_EXTERNAL_IMPORT }; static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, AVVkFrame *frame, enum PrepMode pmode) { int err; - uint32_t dst_qf; + uint32_t src_qf, dst_qf; VkImageLayout new_layout; VkAccessFlags new_access; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; + uint64_t sem_sig_val[AV_NUM_DATA_POINTERS]; VkImageMemoryBarrier img_bar[AV_NUM_DATA_POINTERS] = { 0 }; + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pSignalSemaphoreValues = sem_sig_val, + .signalSemaphoreValueCount = planes, + }; + VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, .pSignalSemaphores = frame->sem, .signalSemaphoreCount = planes, }; VkPipelineStageFlagBits wait_st[AV_NUM_DATA_POINTERS]; - for (int i = 0; i < planes; i++) + for (int i = 0; i < planes; i++) { wait_st[i] = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; + sem_sig_val[i] = frame->sem_value[i] + 1; + } switch (pmode) { case PREP_MODE_WRITE: new_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; new_access = VK_ACCESS_TRANSFER_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_IGNORED; break; - case PREP_MODE_RO_SHADER: - new_layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - new_access = VK_ACCESS_TRANSFER_READ_BIT; + case PREP_MODE_EXTERNAL_IMPORT: + new_layout = VK_IMAGE_LAYOUT_GENERAL; + new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; dst_qf = VK_QUEUE_FAMILY_IGNORED; + s_timeline_sem_info.pWaitSemaphoreValues = frame->sem_value; + s_timeline_sem_info.waitSemaphoreValueCount = planes; + s_info.pWaitSemaphores = frame->sem; + s_info.pWaitDstStageMask = wait_st; + s_info.waitSemaphoreCount = planes; break; case PREP_MODE_EXTERNAL_EXPORT: new_layout = VK_IMAGE_LAYOUT_GENERAL; new_access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT; + src_qf = VK_QUEUE_FAMILY_IGNORED; dst_qf = VK_QUEUE_FAMILY_EXTERNAL_KHR; + s_timeline_sem_info.pWaitSemaphoreValues = frame->sem_value; + s_timeline_sem_info.waitSemaphoreValueCount = planes; s_info.pWaitSemaphores = frame->sem; s_info.pWaitDstStageMask = wait_st; s_info.waitSemaphoreCount = planes; @@ -1778,7 +1976,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, img_bar[i].dstAccessMask = new_access; img_bar[i].oldLayout = frame->layout[i]; img_bar[i].newLayout = new_layout; - img_bar[i].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + img_bar[i].srcQueueFamilyIndex = src_qf; img_bar[i].dstQueueFamilyIndex = dst_qf; img_bar[i].image = frame->img[i]; img_bar[i].subresourceRange.levelCount = 1; @@ -1794,7 +1992,7 @@ static int prepare_frame(AVHWFramesContext *hwfc, VulkanExecCtx *ectx, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, NULL, 0, NULL, planes, img_bar); - return submit_exec_ctx(hwfc, ectx, &s_info, 0); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, 0); } static inline void get_plane_wh(int *w, int *h, enum AVPixelFormat format, @@ -1822,7 +2020,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkResult ret; AVHWDeviceContext *ctx = hwfc->device_ctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVVulkanDeviceContext *hwctx = ctx->hwctx; enum AVPixelFormat format = hwfc->sw_format; const VkFormat *img_fmts = av_vkfmt_from_pixfmt(format); @@ -1830,12 +2028,29 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, VkExportSemaphoreCreateInfo ext_sem_info = { .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, +#ifdef _WIN32 + .handleTypes = IsWindows8OrGreater() + ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, +#else .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, +#endif + }; + + VkSemaphoreTypeCreateInfo sem_type_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, +#ifdef _WIN32 + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM ? &ext_sem_info : NULL, +#else + .pNext = p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, +#endif + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0, }; VkSemaphoreCreateInfo sem_spawn = { .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - .pNext = p->extensions & EXT_EXTERNAL_FD_SEM ? &ext_sem_info : NULL, + .pNext = &sem_type_info, }; AVVkFrame *f = av_vk_frame_alloc(); @@ -1888,6 +2103,7 @@ static int create_frame(AVHWFramesContext *hwfc, AVVkFrame **frame, f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; + f->sem_value[i] = 0; } f->flags = 0x0; @@ -1911,7 +2127,14 @@ static void try_export_flags(AVHWFramesContext *hwfc, AVVulkanFramesContext *hwctx = hwfc->hwctx; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; + + const VkImageDrmFormatModifierListCreateInfoEXT *drm_mod_info = + vk_find_struct(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + int has_mods = hwctx->tiling == VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT && drm_mod_info; + int nb_mods; + VkExternalImageFormatProperties eprops = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, }; @@ -1919,9 +2142,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, .pNext = &eprops, }; + VkPhysicalDeviceImageDrmFormatModifierInfoEXT phy_dev_mod_info = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, + .pNext = NULL, + .pQueueFamilyIndices = p->qfs, + .queueFamilyIndexCount = p->num_qfs, + .sharingMode = p->num_qfs > 1 ? VK_SHARING_MODE_CONCURRENT : + VK_SHARING_MODE_EXCLUSIVE, + }; VkPhysicalDeviceExternalImageFormatInfo enext = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, .handleType = exp, + .pNext = has_mods ? &phy_dev_mod_info : NULL, }; VkPhysicalDeviceImageFormatInfo2 pinfo = { .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, @@ -1933,11 +2165,18 @@ static void try_export_flags(AVHWFramesContext *hwfc, .flags = VK_IMAGE_CREATE_ALIAS_BIT, }; - ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, - &pinfo, &props); - if (ret == VK_SUCCESS) { - *iexp |= exp; - *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; + nb_mods = has_mods ? drm_mod_info->drmFormatModifierCount : 1; + for (int i = 0; i < nb_mods; i++) { + if (has_mods) + phy_dev_mod_info.drmFormatModifier = drm_mod_info->pDrmFormatModifiers[i]; + + ret = vk->GetPhysicalDeviceImageFormatProperties2(dev_hwctx->phys_dev, + &pinfo, &props); + + if (ret == VK_SUCCESS) { + *iexp |= exp; + *comp_handle_types |= eprops.externalMemoryProperties.compatibleHandleTypes; + } } } @@ -1958,13 +2197,20 @@ static AVBufferRef *vulkan_pool_alloc(void *opaque, size_t size) .pNext = hwctx->create_pnext, }; - if (p->extensions & EXT_EXTERNAL_FD_MEMORY) +#ifdef _WIN32 + if (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) + try_export_flags(hwfc, &eiinfo.handleTypes, &e, IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT); +#else + if (p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) try_export_flags(hwfc, &eiinfo.handleTypes, &e, VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT); +#endif for (int i = 0; i < av_pix_fmt_count_planes(hwfc->sw_format); i++) { eminfo[i].sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO; @@ -2001,6 +2247,12 @@ static void vulkan_frames_uninit(AVHWFramesContext *hwfc) { VulkanFramesPriv *fp = hwfc->internal->priv; + if (fp->modifier_info) { + if (fp->modifier_info->pDrmFormatModifiers) + av_freep(&fp->modifier_info->pDrmFormatModifiers); + av_freep(&fp->modifier_info); + } + free_exec_ctx(hwfc, &fp->conv_ctx); free_exec_ctx(hwfc, &fp->upload_ctx); free_exec_ctx(hwfc, &fp->download_ctx); @@ -2014,23 +2266,119 @@ static int vulkan_frames_init(AVHWFramesContext *hwfc) VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *dev_hwctx = hwfc->device_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; + const VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; + const int has_modifiers = !!(p->extensions & FF_VK_EXT_DRM_MODIFIER_FLAGS); - /* Default pool flags */ - hwctx->tiling = hwctx->tiling ? hwctx->tiling : p->use_linear_images ? - VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + /* Default tiling flags */ + hwctx->tiling = hwctx->tiling ? hwctx->tiling : + has_modifiers ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : + p->use_linear_images ? VK_IMAGE_TILING_LINEAR : + VK_IMAGE_TILING_OPTIMAL; if (!hwctx->usage) - hwctx->usage = DEFAULT_USAGE_FLAGS; + hwctx->usage = FF_VK_DEFAULT_USAGE_FLAGS; + + if (!(hwctx->flags & AV_VK_FRAME_FLAG_NONE)) { + if (p->contiguous_planes == 1 || + ((p->contiguous_planes == -1) && p->dev_is_intel)) + hwctx->flags |= AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY; + } + + modifier_info = vk_find_struct(hwctx->create_pnext, + VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT); + + /* Get the supported modifiers if the user has not given any. */ + if (has_modifiers && !modifier_info) { + const VkFormat *fmt = av_vkfmt_from_pixfmt(hwfc->sw_format); + VkImageDrmFormatModifierListCreateInfoEXT *modifier_info; + FFVulkanFunctions *vk = &p->vkfn; + VkDrmFormatModifierPropertiesEXT *mod_props; + uint64_t *modifiers; + int modifier_count = 0; + + VkDrmFormatModifierPropertiesListEXT mod_props_list = { + .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, + .pNext = NULL, + .drmFormatModifierCount = 0, + .pDrmFormatModifierProperties = NULL, + }; + VkFormatProperties2 prop = { + .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, + .pNext = &mod_props_list, + }; + + /* Get all supported modifiers */ + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop); + + if (!mod_props_list.drmFormatModifierCount) { + av_log(hwfc, AV_LOG_ERROR, "There are no supported modifiers for the given sw_format\n"); + return AVERROR(EINVAL); + } + + /* Createa structure to hold the modifier list info */ + modifier_info = av_mallocz(sizeof(*modifier_info)); + if (!modifier_info) + return AVERROR(ENOMEM); + + modifier_info->pNext = NULL; + modifier_info->sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT; + + /* Add structure to the image creation pNext chain */ + if (!hwctx->create_pnext) + hwctx->create_pnext = modifier_info; + else + vk_link_struct(hwctx->create_pnext, (void *)modifier_info); + + /* Backup the allocated struct to be freed later */ + fp->modifier_info = modifier_info; + + /* Allocate list of modifiers */ + modifiers = av_mallocz(mod_props_list.drmFormatModifierCount * + sizeof(*modifiers)); + if (!modifiers) + return AVERROR(ENOMEM); + + modifier_info->pDrmFormatModifiers = modifiers; + + /* Allocate a temporary list to hold all modifiers supported */ + mod_props = av_mallocz(mod_props_list.drmFormatModifierCount * + sizeof(*mod_props)); + if (!mod_props) + return AVERROR(ENOMEM); + + mod_props_list.pDrmFormatModifierProperties = mod_props; + + /* Finally get all modifiers from the device */ + vk->GetPhysicalDeviceFormatProperties2(dev_hwctx->phys_dev, fmt[0], &prop); + + /* Reject any modifiers that don't match our requirements */ + for (int i = 0; i < mod_props_list.drmFormatModifierCount; i++) { + if (!(mod_props[i].drmFormatModifierTilingFeatures & hwctx->usage)) + continue; + + modifiers[modifier_count++] = mod_props[i].drmFormatModifier; + } + + if (!modifier_count) { + av_log(hwfc, AV_LOG_ERROR, "None of the given modifiers supports" + " the usage flags!\n"); + av_freep(&mod_props); + return AVERROR(EINVAL); + } + + modifier_info->drmFormatModifierCount = modifier_count; + av_freep(&mod_props); + } err = create_exec_ctx(hwfc, &fp->conv_ctx, dev_hwctx->queue_family_comp_index, - GET_QUEUE_COUNT(dev_hwctx, 0, 1, 0)); + dev_hwctx->nb_comp_queues); if (err) return err; err = create_exec_ctx(hwfc, &fp->upload_ctx, dev_hwctx->queue_family_tx_index, - GET_QUEUE_COUNT(dev_hwctx, 0, 0, 1)); + dev_hwctx->nb_tx_queues); if (err) return err; @@ -2100,7 +2448,7 @@ static void vulkan_unmap_frame(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; /* Check if buffer needs flushing */ if ((map->flags & AV_HWFRAME_MAP_WRITE) && @@ -2132,12 +2480,13 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src, int flags) { VkResult ret; - int err, mapped_mem_count = 0; + int err, mapped_mem_count = 0, mem_planes = 0; AVVkFrame *f = (AVVkFrame *)src->data[0]; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanMapping *map = av_mallocz(sizeof(VulkanMapping)); if (!map) @@ -2161,7 +2510,8 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; - for (int i = 0; i < planes; i++) { + mem_planes = hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY ? 1 : planes; + for (int i = 0; i < mem_planes; i++) { ret = vk->MapMemory(hwctx->act_dev, f->mem[i], 0, VK_WHOLE_SIZE, 0, (void **)&dst->data[i]); if (ret != VK_SUCCESS) { @@ -2173,6 +2523,11 @@ static int vulkan_map_frame_to_mem(AVHWFramesContext *hwfc, AVFrame *dst, mapped_mem_count++; } + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) { + for (int i = 0; i < planes; i++) + dst->data[i] = dst->data[0] + f->offset[i]; + } + /* Check if the memory contents matter */ if (((flags & AV_HWFRAME_MAP_READ) || !(flags & AV_HWFRAME_MAP_OVERWRITE)) && !(f->flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)) { @@ -2221,21 +2576,33 @@ fail: } #if CONFIG_LIBDRM -static void vulkan_unmap_from(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) +static void vulkan_unmap_from_drm(AVHWFramesContext *hwfc, HWMapDescriptor *hwmap) { - VulkanMapping *map = hwmap->priv; + AVVkFrame *f = hwmap->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; + + VkSemaphoreWaitInfo wait_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .flags = 0x0, + .pSemaphores = f->sem, + .pValues = f->sem_value, + .semaphoreCount = planes, + }; + + vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + + vulkan_free_internal(f); for (int i = 0; i < planes; i++) { - vk->DestroyImage(hwctx->act_dev, map->frame->img[i], hwctx->alloc); - vk->FreeMemory(hwctx->act_dev, map->frame->mem[i], hwctx->alloc); - vk->DestroySemaphore(hwctx->act_dev, map->frame->sem[i], hwctx->alloc); + vk->DestroyImage(hwctx->act_dev, f->img[i], hwctx->alloc); + vk->FreeMemory(hwctx->act_dev, f->mem[i], hwctx->alloc); + vk->DestroySemaphore(hwctx->act_dev, f->sem[i], hwctx->alloc); } - av_freep(&map->frame); + av_free(f); } static const struct { @@ -2272,15 +2639,11 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f AVHWDeviceContext *ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; - AVVulkanFramesContext *frames_hwctx = hwfc->hwctx; const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor *)src->data[0]; - const int has_modifiers = !!(p->extensions & EXT_DRM_MODIFIER_FLAGS); - VkSubresourceLayout plane_data[AV_NUM_DATA_POINTERS] = { 0 }; - VkBindImageMemoryInfo bind_info[AV_NUM_DATA_POINTERS] = { 0 }; - VkBindImagePlaneMemoryInfo plane_info[AV_NUM_DATA_POINTERS] = { 0 }; - VkExternalMemoryHandleTypeFlagBits htype = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; + VkBindImageMemoryInfo bind_info[AV_DRM_MAX_PLANES]; + VkBindImagePlaneMemoryInfo plane_info[AV_DRM_MAX_PLANES]; for (int i = 0; i < desc->nb_layers; i++) { if (drm_to_vulkan_fmt(desc->layers[i].format) == VK_FORMAT_UNDEFINED) { @@ -2296,41 +2659,48 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f goto fail; } - f->tiling = has_modifiers ? VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT : - desc->objects[0].format_modifier == DRM_FORMAT_MOD_LINEAR ? - VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL; + f->tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; for (int i = 0; i < desc->nb_layers; i++) { const int planes = desc->layers[i].nb_planes; - VkImageDrmFormatModifierExplicitCreateInfoEXT drm_info = { + + /* Semaphore */ + VkSemaphoreTypeCreateInfo sem_type_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, + .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, + .initialValue = 0, + }; + VkSemaphoreCreateInfo sem_spawn = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + .pNext = &sem_type_info, + }; + + /* Image creation */ + VkSubresourceLayout ext_img_layouts[AV_DRM_MAX_PLANES]; + VkImageDrmFormatModifierExplicitCreateInfoEXT ext_img_mod_spec = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_EXPLICIT_CREATE_INFO_EXT, .drmFormatModifier = desc->objects[0].format_modifier, .drmFormatModifierPlaneCount = planes, - .pPlaneLayouts = (const VkSubresourceLayout *)&plane_data, + .pPlaneLayouts = (const VkSubresourceLayout *)&ext_img_layouts, }; - - VkExternalMemoryImageCreateInfo einfo = { + VkExternalMemoryImageCreateInfo ext_img_spec = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO, - .pNext = has_modifiers ? &drm_info : NULL, - .handleTypes = htype, + .pNext = &ext_img_mod_spec, + .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; - - VkSemaphoreCreateInfo sem_spawn = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - }; - VkImageCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, - .pNext = &einfo, + .pNext = &ext_img_spec, .imageType = VK_IMAGE_TYPE_2D, .format = drm_to_vulkan_fmt(desc->layers[i].format), .extent.depth = 1, .mipLevels = 1, .arrayLayers = 1, - .flags = VK_IMAGE_CREATE_ALIAS_BIT, + .flags = 0x0, /* ALIAS flag is implicit for imported images */ .tiling = f->tiling, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, /* specs say so */ - .usage = frames_hwctx->usage, + .usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT, .samples = VK_SAMPLE_COUNT_1_BIT, .pQueueFamilyIndices = p->qfs, .queueFamilyIndexCount = p->num_qfs, @@ -2338,15 +2708,57 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f VK_SHARING_MODE_EXCLUSIVE, }; + /* Image format verification */ + VkExternalImageFormatProperties ext_props = { + .sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES_KHR, + }; + VkImageFormatProperties2 props_ret = { + .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, + .pNext = &ext_props, + }; + VkPhysicalDeviceImageDrmFormatModifierInfoEXT props_drm_mod = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, + .drmFormatModifier = ext_img_mod_spec.drmFormatModifier, + .pQueueFamilyIndices = create_info.pQueueFamilyIndices, + .queueFamilyIndexCount = create_info.queueFamilyIndexCount, + .sharingMode = create_info.sharingMode, + }; + VkPhysicalDeviceExternalImageFormatInfo props_ext = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO, + .pNext = &props_drm_mod, + .handleType = ext_img_spec.handleTypes, + }; + VkPhysicalDeviceImageFormatInfo2 fmt_props = { + .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, + .pNext = &props_ext, + .format = create_info.format, + .type = create_info.imageType, + .tiling = create_info.tiling, + .usage = create_info.usage, + .flags = create_info.flags, + }; + + /* Check if importing is possible for this combination of parameters */ + ret = vk->GetPhysicalDeviceImageFormatProperties2(hwctx->phys_dev, + &fmt_props, &props_ret); + if (ret != VK_SUCCESS) { + av_log(ctx, AV_LOG_ERROR, "Cannot map DRM frame to Vulkan: %s\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + + /* Set the image width/height */ get_plane_wh(&create_info.extent.width, &create_info.extent.height, hwfc->sw_format, src->width, src->height, i); + /* Set the subresource layout based on the layer properties */ for (int j = 0; j < planes; j++) { - plane_data[j].offset = desc->layers[i].planes[j].offset; - plane_data[j].rowPitch = desc->layers[i].planes[j].pitch; - plane_data[j].size = 0; /* The specs say so for all 3 */ - plane_data[j].arrayPitch = 0; - plane_data[j].depthPitch = 0; + ext_img_layouts[j].offset = desc->layers[i].planes[j].offset; + ext_img_layouts[j].rowPitch = desc->layers[i].planes[j].pitch; + ext_img_layouts[j].size = 0; /* The specs say so for all 3 */ + ext_img_layouts[j].arrayPitch = 0; + ext_img_layouts[j].depthPitch = 0; } /* Create image */ @@ -2374,27 +2786,41 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f f->layout[i] = create_info.initialLayout; f->access[i] = 0x0; + f->sem_value[i] = 0; } for (int i = 0; i < desc->nb_objects; i++) { - int use_ded_mem = 0; + /* Memory requirements */ + VkImageMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, + .image = f->img[i], + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req2 = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + /* Allocation/importing */ VkMemoryFdPropertiesKHR fdmp = { .sType = VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR, }; - VkMemoryRequirements req = { - .size = desc->objects[i].size, - }; VkImportMemoryFdInfoKHR idesc = { .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR, - .handleType = htype, .fd = dup(desc->objects[i].fd), + .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, }; VkMemoryDedicatedAllocateInfo ded_alloc = { .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, .pNext = &idesc, + .image = req_desc.image, }; - ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev, htype, + /* Get object properties */ + ret = vk->GetMemoryFdPropertiesKHR(hwctx->act_dev, + VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, idesc.fd, &fdmp); if (ret != VK_SUCCESS) { av_log(hwfc, AV_LOG_ERROR, "Failed to get FD properties: %s\n", @@ -2404,59 +2830,44 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f goto fail; } - req.memoryTypeBits = fdmp.memoryTypeBits; + vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2); - /* Dedicated allocation only makes sense if there's a one to one mapping - * between images and the memory backing them, so only check in this - * case. */ - if (desc->nb_layers == desc->nb_objects) { - VkImageMemoryRequirementsInfo2 req_desc = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, - .image = f->img[i], - }; - VkMemoryDedicatedRequirements ded_req = { - .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, - }; - VkMemoryRequirements2 req2 = { - .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, - .pNext = &ded_req, - }; + /* Only a single bit must be set, not a range, and it must match */ + req2.memoryRequirements.memoryTypeBits = fdmp.memoryTypeBits; - vk->GetImageMemoryRequirements2(hwctx->act_dev, &req_desc, &req2); - - use_ded_mem = ded_req.prefersDedicatedAllocation | - ded_req.requiresDedicatedAllocation; - if (use_ded_mem) - ded_alloc.image = f->img[i]; - } - - err = alloc_mem(ctx, &req, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - use_ded_mem ? &ded_alloc : ded_alloc.pNext, + err = alloc_mem(ctx, &req2.memoryRequirements, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + (ded_req.prefersDedicatedAllocation || + ded_req.requiresDedicatedAllocation) ? + &ded_alloc : ded_alloc.pNext, &f->flags, &f->mem[i]); if (err) { close(idesc.fd); return err; } - f->size[i] = desc->objects[i].size; + f->size[i] = req2.memoryRequirements.size; } for (int i = 0; i < desc->nb_layers; i++) { const int planes = desc->layers[i].nb_planes; - const int signal_p = has_modifiers && (planes > 1); for (int j = 0; j < planes; j++) { VkImageAspectFlagBits aspect = j == 0 ? VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : j == 1 ? VK_IMAGE_ASPECT_MEMORY_PLANE_1_BIT_EXT : VK_IMAGE_ASPECT_MEMORY_PLANE_2_BIT_EXT; plane_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_PLANE_MEMORY_INFO; + plane_info[bind_counts].pNext = NULL; plane_info[bind_counts].planeAspect = aspect; bind_info[bind_counts].sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO; - bind_info[bind_counts].pNext = signal_p ? &plane_info[bind_counts] : NULL; + bind_info[bind_counts].pNext = planes > 1 ? &plane_info[bind_counts] : NULL; bind_info[bind_counts].image = f->img[i]; bind_info[bind_counts].memory = f->mem[desc->layers[i].planes[j].object_index]; - bind_info[bind_counts].memoryOffset = desc->layers[i].planes[j].offset; + + /* Offset is already signalled via pPlaneLayouts above */ + bind_info[bind_counts].memoryOffset = 0; + bind_counts++; } } @@ -2466,13 +2877,11 @@ static int vulkan_map_from_drm_frame_desc(AVHWFramesContext *hwfc, AVVkFrame **f if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to bind memory: %s\n", vk_ret2str(ret)); - return AVERROR_EXTERNAL; + err = AVERROR_EXTERNAL; + goto fail; } - /* NOTE: This is completely uneccesary and unneeded once we can import - * semaphores from DRM. Otherwise we have to activate the semaphores. - * We're reusing the exec context that's also used for uploads/downloads. */ - err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_RO_SHADER); + err = prepare_frame(hwfc, &fp->conv_ctx, f, PREP_MODE_EXTERNAL_IMPORT); if (err) goto fail; @@ -2498,7 +2907,6 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, { int err = 0; AVVkFrame *f; - VulkanMapping *map = NULL; if ((err = vulkan_map_from_drm_frame_desc(hwfc, &f, src))) return err; @@ -2508,15 +2916,8 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, dst->width = src->width; dst->height = src->height; - map = av_mallocz(sizeof(VulkanMapping)); - if (!map) - goto fail; - - map->frame = f; - map->flags = flags; - err = ff_hwframe_map_create(dst->hw_frames_ctx, dst, src, - &vulkan_unmap_from, map); + &vulkan_unmap_from_drm, f); if (err < 0) goto fail; @@ -2526,7 +2927,6 @@ static int vulkan_map_from_drm(AVHWFramesContext *hwfc, AVFrame *dst, fail: vulkan_frame_free(hwfc->device_ctx->hwctx, (uint8_t *)f); - av_free(map); return err; } @@ -2580,7 +2980,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVHWFramesContext *cuda_fc = (AVHWFramesContext*)cuda_hwfc->data; AVHWDeviceContext *cuda_cu = cuda_fc->device_ctx; @@ -2597,15 +2997,13 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, if (!dst_f->internal) dst_f->internal = dst_int = av_mallocz(sizeof(*dst_f->internal)); - if (!dst_int) { - err = AVERROR(ENOMEM); - goto fail; - } + if (!dst_int) + return AVERROR(ENOMEM); dst_int->cuda_fc_ref = av_buffer_ref(cuda_hwfc); if (!dst_int->cuda_fc_ref) { - err = AVERROR(ENOMEM); - goto fail; + av_freep(&dst_f->internal); + return AVERROR(ENOMEM); } for (int i = 0; i < planes; i++) { @@ -2619,6 +3017,43 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, }, .numLevels = 1, }; + int p_w, p_h; + +#ifdef _WIN32 + CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = { + .type = IsWindows8OrGreater() + ? CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32 + : CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT, + .size = dst_f->size[i], + }; + VkMemoryGetWin32HandleInfoKHR export_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR, + .memory = dst_f->mem[i], + .handleType = IsWindows8OrGreater() + ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + }; + VkSemaphoreGetWin32HandleInfoKHR sem_export = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR, + .semaphore = dst_f->sem[i], + .handleType = IsWindows8OrGreater() + ? VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT + : VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT, + }; + CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = { + .type = 10 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_WIN32 */, + }; + + ret = vk->GetMemoryWin32HandleKHR(hwctx->act_dev, &export_info, + &ext_desc.handle.win32.handle); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a Win32 Handle: %s!\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } + dst_int->ext_mem_handle[i] = ext_desc.handle.win32.handle; +#else CUDA_EXTERNAL_MEMORY_HANDLE_DESC ext_desc = { .type = CU_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD, .size = dst_f->size[i], @@ -2634,28 +3069,31 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT, }; CUDA_EXTERNAL_SEMAPHORE_HANDLE_DESC ext_sem_desc = { - .type = CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD, + .type = 9 /* TODO: CU_EXTERNAL_SEMAPHORE_HANDLE_TYPE_TIMELINE_SEMAPHORE_FD */, }; - int p_w, p_h; - get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i); - - tex_desc.arrayDesc.Width = p_w; - tex_desc.arrayDesc.Height = p_h; - ret = vk->GetMemoryFdKHR(hwctx->act_dev, &export_info, &ext_desc.handle.fd); if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD!\n"); + av_log(hwfc, AV_LOG_ERROR, "Unable to export the image as a FD: %s!\n", + vk_ret2str(ret)); + err = AVERROR_EXTERNAL; + goto fail; + } +#endif + + ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[i], &ext_desc)); + if (ret < 0) { +#ifndef _WIN32 + close(ext_desc.handle.fd); +#endif err = AVERROR_EXTERNAL; goto fail; } - ret = CHECK_CU(cu->cuImportExternalMemory(&dst_int->ext_mem[i], &ext_desc)); - if (ret < 0) { - err = AVERROR_EXTERNAL; - goto fail; - } + get_plane_wh(&p_w, &p_h, hwfc->sw_format, hwfc->width, hwfc->height, i); + tex_desc.arrayDesc.Width = p_w; + tex_desc.arrayDesc.Height = p_h; ret = CHECK_CU(cu->cuExternalMemoryGetMappedMipmappedArray(&dst_int->cu_mma[i], dst_int->ext_mem[i], @@ -2672,18 +3110,29 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, goto fail; } +#ifdef _WIN32 + ret = vk->GetSemaphoreWin32HandleKHR(hwctx->act_dev, &sem_export, + &ext_sem_desc.handle.win32.handle); +#else ret = vk->GetSemaphoreFdKHR(hwctx->act_dev, &sem_export, &ext_sem_desc.handle.fd); +#endif if (ret != VK_SUCCESS) { av_log(ctx, AV_LOG_ERROR, "Failed to export semaphore: %s\n", vk_ret2str(ret)); err = AVERROR_EXTERNAL; goto fail; } +#ifdef _WIN32 + dst_int->ext_sem_handle[i] = ext_sem_desc.handle.win32.handle; +#endif ret = CHECK_CU(cu->cuImportExternalSemaphore(&dst_int->cu_sem[i], &ext_sem_desc)); if (ret < 0) { +#ifndef _WIN32 + close(ext_sem_desc.handle.fd); +#endif err = AVERROR_EXTERNAL; goto fail; } @@ -2693,6 +3142,7 @@ static int vulkan_export_to_cuda(AVHWFramesContext *hwfc, return 0; fail: + vulkan_free_internal(dst_f); return err; } @@ -2700,10 +3150,10 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src) { int err; - VkResult ret; CUcontext dummy; AVVkFrame *dst_f; AVVkFrameInternal *dst_int; + VulkanFramesPriv *fp = hwfc->internal->priv; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); @@ -2715,27 +3165,34 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 }; CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 }; - ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); - if (ret < 0) - return AVERROR_EXTERNAL; - dst_f = (AVVkFrame *)dst->data[0]; - ret = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst); - if (ret < 0) { + err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + if (err < 0) + return err; + + err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); + if (err < 0) + return err; + + err = vulkan_export_to_cuda(hwfc, src->hw_frames_ctx, dst); + if (err < 0) { CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - return ret; + return err; } dst_int = dst_f->internal; - ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, - planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; - goto fail; + for (int i = 0; i < planes; i++) { + s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0; + s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; } + err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, + planes, cuda_dev->stream)); + if (err < 0) + goto fail; + for (int i = 0; i < planes; i++) { CUDA_MEMCPY2D cpy = { .srcMemoryType = CU_MEMORYTYPE_DEVICE, @@ -2753,29 +3210,28 @@ static int vulkan_transfer_data_from_cuda(AVHWFramesContext *hwfc, cpy.WidthInBytes = p_w * desc->comp[i].step; cpy.Height = p_h; - ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); + if (err < 0) goto fail; - } } - ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } + + for (int i = 0; i < planes; i++) + dst_f->sem_value[i]++; CHECK_CU(cu->cuCtxPopCurrent(&dummy)); av_log(hwfc, AV_LOG_VERBOSE, "Transfered CUDA image to Vulkan!\n"); - return 0; + return err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - vulkan_free_internal(dst_int); + vulkan_free_internal(dst_f); dst_f->internal = NULL; av_buffer_unref(&dst->buf[0]); return err; @@ -2791,12 +3247,16 @@ static int vulkan_map_to(AVHWFramesContext *hwfc, AVFrame *dst, #if CONFIG_LIBDRM #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_vaapi(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_from_drm(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif default: return AVERROR(ENOSYS); @@ -2834,13 +3294,19 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, VkResult ret; AVVkFrame *f = (AVVkFrame *)src->data[0]; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VulkanFramesPriv *fp = hwfc->internal->priv; AVVulkanDeviceContext *hwctx = hwfc->device_ctx->hwctx; + AVVulkanFramesContext *hwfctx = hwfc->hwctx; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); VkImageDrmFormatModifierPropertiesEXT drm_mod = { .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, }; + VkSemaphoreWaitInfo wait_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, + .flags = 0x0, + .semaphoreCount = planes, + }; AVDRMFrameDescriptor *drm_desc = av_mallocz(sizeof(*drm_desc)); if (!drm_desc) @@ -2850,18 +3316,22 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, if (err < 0) goto end; + /* Wait for the operation to finish so we can cleanly export it. */ + wait_info.pSemaphores = f->sem; + wait_info.pValues = f->sem_value; + + vk->WaitSemaphores(hwctx->act_dev, &wait_info, UINT64_MAX); + err = ff_hwframe_map_create(src->hw_frames_ctx, dst, src, &vulkan_unmap_to_drm, drm_desc); if (err < 0) goto end; - if (p->extensions & EXT_DRM_MODIFIER_FLAGS) { - ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0], - &drm_mod); - if (ret != VK_SUCCESS) { - av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n"); - err = AVERROR_EXTERNAL; - goto end; - } + ret = vk->GetImageDrmFormatModifierPropertiesEXT(hwctx->act_dev, f->img[0], + &drm_mod); + if (ret != VK_SUCCESS) { + av_log(hwfc, AV_LOG_ERROR, "Failed to retrieve DRM format modifier!\n"); + err = AVERROR_EXTERNAL; + goto end; } for (int i = 0; (i < planes) && (f->mem[i]); i++) { @@ -2888,9 +3358,7 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, for (int i = 0; i < drm_desc->nb_layers; i++) { VkSubresourceLayout layout; VkImageSubresource sub = { - .aspectMask = p->extensions & EXT_DRM_MODIFIER_FLAGS ? - VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT : - VK_IMAGE_ASPECT_COLOR_BIT, + .aspectMask = VK_IMAGE_ASPECT_MEMORY_PLANE_0_BIT_EXT, }; VkFormat plane_vkfmt = av_vkfmt_from_pixfmt(hwfc->sw_format)[i]; @@ -2909,8 +3377,11 @@ static int vulkan_map_to_drm(AVHWFramesContext *hwfc, AVFrame *dst, continue; vk->GetImageSubresourceLayout(hwctx->act_dev, f->img[i], &sub, &layout); - drm_desc->layers[i].planes[0].offset = layout.offset; - drm_desc->layers[i].planes[0].pitch = layout.rowPitch; + drm_desc->layers[i].planes[0].offset = layout.offset; + drm_desc->layers[i].planes[0].pitch = layout.rowPitch; + + if (hwfctx->flags & AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY) + drm_desc->layers[i].planes[0].offset += f->offset[i]; } dst->width = src->width; @@ -2962,12 +3433,16 @@ static int vulkan_map_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_LIBDRM case AV_PIX_FMT_DRM_PRIME: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_drm(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #if CONFIG_VAAPI case AV_PIX_FMT_VAAPI: - if (p->extensions & EXT_EXTERNAL_DMABUF_MEMORY) + if (p->extensions & (FF_VK_EXT_EXTERNAL_DMABUF_MEMORY | FF_VK_EXT_DRM_MODIFIER_FLAGS)) return vulkan_map_to_vaapi(hwfc, dst, src, flags); + else + return AVERROR(ENOSYS); #endif #endif default: @@ -2987,7 +3462,7 @@ static void free_buf(void *opaque, uint8_t *data) AVHWDeviceContext *ctx = opaque; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; ImageBuffer *vkbuf = (ImageBuffer *)data; if (vkbuf->buf) @@ -3017,7 +3492,7 @@ static int create_buf(AVHWDeviceContext *ctx, AVBufferRef **buf, int use_ded_mem; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkBufferCreateInfo buf_spawn = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, @@ -3104,7 +3579,7 @@ static int map_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, uint8_t *mem[ VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange invalidate_ctx[AV_NUM_DATA_POINTERS]; int invalidate_count = 0; @@ -3163,7 +3638,7 @@ static int unmap_buffers(AVHWDeviceContext *ctx, AVBufferRef **bufs, VkResult ret; AVVulkanDeviceContext *hwctx = ctx->hwctx; VulkanDevicePriv *p = ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; VkMappedMemoryRange flush_ctx[AV_NUM_DATA_POINTERS]; int flush_count = 0; @@ -3212,7 +3687,7 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, AVVkFrame *frame = (AVVkFrame *)f->data[0]; VulkanFramesPriv *fp = hwfc->internal->priv; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; int bar_num = 0; VkPipelineStageFlagBits sem_wait_dst[AV_NUM_DATA_POINTERS]; @@ -3224,8 +3699,19 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, VulkanExecCtx *ectx = to_buf ? &fp->download_ctx : &fp->upload_ctx; VkCommandBuffer cmd_buf = get_buf_exec_ctx(hwfc, ectx); + uint64_t sem_signal_values[AV_NUM_DATA_POINTERS]; + + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pWaitSemaphoreValues = frame->sem_value, + .pSignalSemaphoreValues = sem_signal_values, + .waitSemaphoreValueCount = planes, + .signalSemaphoreValueCount = planes, + }; + VkSubmitInfo s_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, .pSignalSemaphores = frame->sem, .pWaitSemaphores = frame->sem, .pWaitDstStageMask = sem_wait_dst, @@ -3233,6 +3719,9 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, .waitSemaphoreCount = planes, }; + for (int i = 0; i < planes; i++) + sem_signal_values[i] = frame->sem_value[i] + 1; + if ((err = wait_start_exec_ctx(hwfc, ectx))) return err; @@ -3313,9 +3802,9 @@ static int transfer_image_buf(AVHWFramesContext *hwfc, const AVFrame *f, } if (ref && (err = add_buf_dep_exec_ctx(hwfc, ectx, bufs, planes))) return err; - return submit_exec_ctx(hwfc, ectx, &s_info, !ref); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, !ref); } else { - return submit_exec_ctx(hwfc, ectx, &s_info, 1); + return submit_exec_ctx(hwfc, ectx, &s_info, frame, 1); } } @@ -3328,7 +3817,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, AVHWDeviceContext *dev_ctx = hwfc->device_ctx; AVVulkanDeviceContext *hwctx = dev_ctx->hwctx; VulkanDevicePriv *p = hwfc->device_ctx->internal->priv; - VulkanFunctions *vk = &p->vkfn; + FFVulkanFunctions *vk = &p->vkfn; AVFrame tmp; AVBufferRef *bufs[AV_NUM_DATA_POINTERS] = { 0 }; @@ -3338,7 +3827,7 @@ static int vulkan_transfer_data(AVHWFramesContext *hwfc, const AVFrame *vkf, const int planes = av_pix_fmt_count_planes(swf->format); int host_mapped[AV_NUM_DATA_POINTERS] = { 0 }; - const int map_host = !!(p->extensions & EXT_EXTERNAL_HOST_MEMORY); + const int map_host = !!(p->extensions & FF_VK_EXT_EXTERNAL_HOST_MEMORY); if ((swf->format != AV_PIX_FMT_NONE && !av_vkfmt_from_pixfmt(swf->format))) { av_log(hwfc, AV_LOG_ERROR, "Unsupported software frame pixel format!\n"); @@ -3484,8 +3973,13 @@ static int vulkan_transfer_data_to(AVHWFramesContext *hwfc, AVFrame *dst, switch (src->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_from_cuda(hwfc, dst, src); #endif default: @@ -3501,10 +3995,10 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, const AVFrame *src) { int err; - VkResult ret; CUcontext dummy; AVVkFrame *dst_f; AVVkFrameInternal *dst_int; + VulkanFramesPriv *fp = hwfc->internal->priv; const int planes = av_pix_fmt_count_planes(hwfc->sw_format); const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(hwfc->sw_format); @@ -3516,12 +4010,16 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, CUDA_EXTERNAL_SEMAPHORE_WAIT_PARAMS s_w_par[AV_NUM_DATA_POINTERS] = { 0 }; CUDA_EXTERNAL_SEMAPHORE_SIGNAL_PARAMS s_s_par[AV_NUM_DATA_POINTERS] = { 0 }; - ret = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); - if (ret < 0) - return AVERROR_EXTERNAL; - dst_f = (AVVkFrame *)src->data[0]; + err = prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_EXPORT); + if (err < 0) + return err; + + err = CHECK_CU(cu->cuCtxPushCurrent(cuda_dev->cuda_ctx)); + if (err < 0) + return err; + err = vulkan_export_to_cuda(hwfc, dst->hw_frames_ctx, src); if (err < 0) { CHECK_CU(cu->cuCtxPopCurrent(&dummy)); @@ -3530,13 +4028,16 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, dst_int = dst_f->internal; - ret = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, - planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; - goto fail; + for (int i = 0; i < planes; i++) { + s_w_par[i].params.fence.value = dst_f->sem_value[i] + 0; + s_s_par[i].params.fence.value = dst_f->sem_value[i] + 1; } + err = CHECK_CU(cu->cuWaitExternalSemaphoresAsync(dst_int->cu_sem, s_w_par, + planes, cuda_dev->stream)); + if (err < 0) + goto fail; + for (int i = 0; i < planes; i++) { CUDA_MEMCPY2D cpy = { .dstMemoryType = CU_MEMORYTYPE_DEVICE, @@ -3554,29 +4055,28 @@ static int vulkan_transfer_data_to_cuda(AVHWFramesContext *hwfc, AVFrame *dst, cpy.WidthInBytes = w * desc->comp[i].step; cpy.Height = h; - ret = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + err = CHECK_CU(cu->cuMemcpy2DAsync(&cpy, cuda_dev->stream)); + if (err < 0) goto fail; - } } - ret = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, + err = CHECK_CU(cu->cuSignalExternalSemaphoresAsync(dst_int->cu_sem, s_s_par, planes, cuda_dev->stream)); - if (ret < 0) { - err = AVERROR_EXTERNAL; + if (err < 0) goto fail; - } + + for (int i = 0; i < planes; i++) + dst_f->sem_value[i]++; CHECK_CU(cu->cuCtxPopCurrent(&dummy)); av_log(hwfc, AV_LOG_VERBOSE, "Transfered Vulkan image to CUDA!\n"); - return 0; + return prepare_frame(hwfc, &fp->upload_ctx, dst_f, PREP_MODE_EXTERNAL_IMPORT); fail: CHECK_CU(cu->cuCtxPopCurrent(&dummy)); - vulkan_free_internal(dst_int); + vulkan_free_internal(dst_f); dst_f->internal = NULL; av_buffer_unref(&dst->buf[0]); return err; @@ -3591,8 +4091,13 @@ static int vulkan_transfer_data_from(AVHWFramesContext *hwfc, AVFrame *dst, switch (dst->format) { #if CONFIG_CUDA case AV_PIX_FMT_CUDA: - if ((p->extensions & EXT_EXTERNAL_FD_MEMORY) && - (p->extensions & EXT_EXTERNAL_FD_SEM)) +#ifdef _WIN32 + if ((p->extensions & FF_VK_EXT_EXTERNAL_WIN32_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_WIN32_SEM)) +#else + if ((p->extensions & FF_VK_EXT_EXTERNAL_FD_MEMORY) && + (p->extensions & FF_VK_EXT_EXTERNAL_FD_SEM)) +#endif return vulkan_transfer_data_to_cuda(hwfc, dst, src); #endif default: diff --git a/libavutil/hwcontext_vulkan.h b/libavutil/hwcontext_vulkan.h index e4645527d7..df86c85b3c 100644 --- a/libavutil/hwcontext_vulkan.h +++ b/libavutil/hwcontext_vulkan.h @@ -19,6 +19,9 @@ #ifndef AVUTIL_HWCONTEXT_VULKAN_H #define AVUTIL_HWCONTEXT_VULKAN_H +#if defined(_WIN32) && !defined(VK_USE_PLATFORM_WIN32_KHR) +#define VK_USE_PLATFORM_WIN32_KHR +#endif #include #include "pixfmt.h" @@ -50,7 +53,7 @@ typedef struct AVVulkanDeviceContext { PFN_vkGetInstanceProcAddr get_proc_addr; /** - * Vulkan instance. Must be at least version 1.1. + * Vulkan instance. Must be at least version 1.2. */ VkInstance inst; @@ -94,40 +97,69 @@ typedef struct AVVulkanDeviceContext { int nb_enabled_dev_extensions; /** - * Queue family index for graphics - * @note av_hwdevice_create() will set all 3 queue indices if unset - * If there is no dedicated queue for compute or transfer operations, - * they will be set to the graphics queue index which can handle both. - * nb_graphics_queues indicates how many queues were enabled for the - * graphics queue (must be at least 1) + * Queue family index for graphics operations, and the number of queues + * enabled for it. If unavaiable, will be set to -1. Not required. + * av_hwdevice_create() will attempt to find a dedicated queue for each + * queue family, or pick the one with the least unrelated flags set. + * Queue indices here may overlap if a queue has to share capabilities. */ int queue_family_index; int nb_graphics_queues; /** - * Queue family index to use for transfer operations, and the amount of queues - * enabled. In case there is no dedicated transfer queue, nb_tx_queues - * must be 0 and queue_family_tx_index must be the same as either the graphics - * queue or the compute queue, if available. + * Queue family index for transfer operations and the number of queues + * enabled. Required. */ int queue_family_tx_index; int nb_tx_queues; /** - * Queue family index for compute ops, and the amount of queues enabled. - * In case there are no dedicated compute queues, nb_comp_queues must be - * 0 and its queue family index must be set to the graphics queue. + * Queue family index for compute operations and the number of queues + * enabled. Required. */ int queue_family_comp_index; int nb_comp_queues; + + /** + * Queue family index for video encode ops, and the amount of queues enabled. + * If the device doesn't support such, queue_family_encode_index will be -1. + * Not required. + */ + int queue_family_encode_index; + int nb_encode_queues; + + /** + * Queue family index for video decode ops, and the amount of queues enabled. + * If the device doesn't support such, queue_family_decode_index will be -1. + * Not required. + */ + int queue_family_decode_index; + int nb_decode_queues; } AVVulkanDeviceContext; +/** + * Defines the behaviour of frame allocation. + */ +typedef enum AVVkFrameFlags { + /* Unless this flag is set, autodetected flags will be OR'd based on the + * device and tiling during av_hwframe_ctx_init(). */ + AV_VK_FRAME_FLAG_NONE = (1ULL << 0), + + /* Image planes will be allocated in a single VkDeviceMemory, rather + * than as per-plane VkDeviceMemory allocations. Required for exporting + * to VAAPI on Intel devices. */ + AV_VK_FRAME_FLAG_CONTIGUOUS_MEMORY = (1ULL << 1), +} AVVkFrameFlags; + /** * Allocated as AVHWFramesContext.hwctx, used to set pool-specific options */ typedef struct AVVulkanFramesContext { /** - * Controls the tiling of allocated frames. + * Controls the tiling of allocated frames. If left as optimal tiling, + * then during av_hwframe_ctx_init() will decide based on whether the device + * supports DRM modifiers, or if the linear_images flag is set, otherwise + * will allocate optimally-tiled images. */ VkImageTiling tiling; @@ -139,6 +171,12 @@ typedef struct AVVulkanFramesContext { /** * Extension data for image creation. + * If VkImageDrmFormatModifierListCreateInfoEXT is present in the chain, + * and the device supports DRM modifiers, then images will be allocated + * with the specific requested DRM modifiers. + * Additional structures may be added at av_hwframe_ctx_init() time, + * which will be freed automatically on uninit(), so users need only free + * any structures they've allocated themselves. */ void *create_pnext; @@ -150,6 +188,13 @@ typedef struct AVVulkanFramesContext { * extensions are present in enabled_dev_extensions. */ void *alloc_pnext[AV_NUM_DATA_POINTERS]; + + /** + * A combination of AVVkFrameFlags. Unless AV_VK_FRAME_FLAG_NONE is set, + * autodetected flags will be OR'd based on the device and tiling during + * av_hwframe_ctx_init(). + */ + AVVkFrameFlags flags; } AVVulkanFramesContext; /* @@ -158,7 +203,7 @@ typedef struct AVVulkanFramesContext { * All frames, imported or allocated, will be created with the * VK_IMAGE_CREATE_ALIAS_BIT flag set, so the memory may be aliased if needed. * - * If all three queue family indices in the device context are the same, + * If all queue family indices in the device context are the same, * images will be created with the EXCLUSIVE sharing mode. Otherwise, all images * will be created using the CONCURRENT sharing mode. * @@ -177,8 +222,9 @@ typedef struct AVVkFrame { VkImageTiling tiling; /** - * Memory backing the images. Could be less than the amount of images - * if importing from a DRM or VAAPI frame. + * Memory backing the images. Could be less than the amount of planes, + * in which case the offset value will indicate the binding offset of + * each plane in the memory. */ VkDeviceMemory mem[AV_NUM_DATA_POINTERS]; size_t size[AV_NUM_DATA_POINTERS]; @@ -195,17 +241,29 @@ typedef struct AVVkFrame { VkImageLayout layout[AV_NUM_DATA_POINTERS]; /** - * Synchronization semaphores. Must not be freed manually. Must be waited on - * and signalled at every queue submission. - * Could be less than the amount of images: either one per VkDeviceMemory - * or one for the entire frame. All others will be set to VK_NULL_HANDLE. + * Synchronization timeline semaphores, one for each sw_format plane. + * Must not be freed manually. Must be waited on at every submission using + * the value in sem_value, and must be signalled at every submission, + * using an incremented value. */ VkSemaphore sem[AV_NUM_DATA_POINTERS]; + /** + * Up to date semaphore value at which each image becomes accessible. + * Clients must wait on this value when submitting a command queue, + * and increment it when signalling. + */ + uint64_t sem_value[AV_NUM_DATA_POINTERS]; + /** * Internal data. */ struct AVVkFrameInternal *internal; + + /** + * Describes the binding offset of each plane to the VkDeviceMemory. + */ + ptrdiff_t offset[AV_NUM_DATA_POINTERS]; } AVVkFrame; /** diff --git a/libavutil/loongarch/Makefile b/libavutil/loongarch/Makefile new file mode 100644 index 0000000000..2addd9351c --- /dev/null +++ b/libavutil/loongarch/Makefile @@ -0,0 +1 @@ +OBJS += loongarch/cpu.o diff --git a/libavutil/loongarch/cpu.c b/libavutil/loongarch/cpu.c new file mode 100644 index 0000000000..e4b240bc44 --- /dev/null +++ b/libavutil/loongarch/cpu.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 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 +#include "cpu.h" + +#define LOONGARCH_CFG2 0x2 +#define LOONGARCH_CFG2_LSX (1 << 6) +#define LOONGARCH_CFG2_LASX (1 << 7) + +static int cpu_flags_cpucfg(void) +{ + int flags = 0; + uint32_t cfg2 = 0; + + __asm__ volatile( + "cpucfg %0, %1 \n\t" + : "+&r"(cfg2) + : "r"(LOONGARCH_CFG2) + ); + + if (cfg2 & LOONGARCH_CFG2_LSX) + flags |= AV_CPU_FLAG_LSX; + + if (cfg2 & LOONGARCH_CFG2_LASX) + flags |= AV_CPU_FLAG_LASX; + + return flags; +} + +int ff_get_cpu_flags_loongarch(void) +{ +#if defined __linux__ + return cpu_flags_cpucfg(); +#else + /* Assume no SIMD ASE supported */ + return 0; +#endif +} + +size_t ff_get_cpu_max_align_loongarch(void) +{ + int flags = av_get_cpu_flags(); + + if (flags & AV_CPU_FLAG_LASX) + return 32; + if (flags & AV_CPU_FLAG_LSX) + return 16; + + return 8; +} diff --git a/libavutil/loongarch/cpu.h b/libavutil/loongarch/cpu.h new file mode 100644 index 0000000000..1a445c69bc --- /dev/null +++ b/libavutil/loongarch/cpu.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 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 AVUTIL_LOONGARCH_CPU_H +#define AVUTIL_LOONGARCH_CPU_H + +#include "libavutil/cpu.h" +#include "libavutil/cpu_internal.h" + +#define have_lsx(flags) CPUEXT(flags, LSX) +#define have_lasx(flags) CPUEXT(flags, LASX) + +#endif /* AVUTIL_LOONGARCH_CPU_H */ diff --git a/libavutil/loongarch/loongson_intrinsics.h b/libavutil/loongarch/loongson_intrinsics.h new file mode 100644 index 0000000000..6e0439f829 --- /dev/null +++ b/libavutil/loongarch/loongson_intrinsics.h @@ -0,0 +1,1877 @@ +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Shiyou Yin + * Xiwei Gu + * Lu 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_LOONGARCH_LOONGSON_INTRINSICS_H +#define AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H + +/* + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Shiyou Yin + * Xiwei Gu + * Lu Wang + * + * This file is a header file for loongarch builtin extention. + * + */ + +#ifndef LOONGSON_INTRINSICS_H +#define LOONGSON_INTRINSICS_H + +/** + * MAJOR version: Macro usage changes. + * MINOR version: Add new functions, or bug fix. + * MICRO version: Comment changes or implementation changes. + */ +#define LSOM_VERSION_MAJOR 1 +#define LSOM_VERSION_MINOR 0 +#define LSOM_VERSION_MICRO 3 + +#define DUP2_ARG1(_INS, _IN0, _IN1, _OUT0, _OUT1) \ +{ \ + _OUT0 = _INS(_IN0); \ + _OUT1 = _INS(_IN1); \ +} + +#define DUP2_ARG2(_INS, _IN0, _IN1, _IN2, _IN3, _OUT0, _OUT1) \ +{ \ + _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); \ +} + +#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); \ +} + +#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); \ +} + +#ifdef __loongarch_sx +#include +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Retrun 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. + * 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 + * 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_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; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Outputs - out + * Retrun 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) + * 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; + + 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 + * 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 + * 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) + * in_c : 1,2,3,4 + * in_h : 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1 + * out : 23,40,41,26 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun 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. + * Example : out = __lsx_vdp2_h_b(in_h, in_l) + * 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 : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun 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. + * Example : out = __lsx_vdp2_h_bu(in_h, in_l) + * 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 : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun 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. + * Example : out = __lsx_vdp2_h_bu_b(in_h, in_l) + * 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 : 22,38,38,22, 22,38,38,6 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Outputs - out + * Retrun 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. + * Example : out = __lsx_vdp2_w_h(in_h, in_l) + * in_h : 1,2,3,4, 5,6,7,8 + * in_l : 8,7,6,5, 4,3,2,1 + * out : 22,38,38,22 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Clip all halfword elements of input vector between min & max + * out = ((_in) < (min)) ? (min) : (((_in) > (max)) ? (max) : (_in)) + * Arguments : Inputs - _in (input vector) + * - min (min threshold) + * - max (max threshold) + * Outputs - out (output vector with clipped elements) + * Return Type - signed halfword + * Example : out = __lsx_vclip_h(_in) + * _in : -8,2,280,249, -8,255,280,249 + * min : 1,1,1,1, 1,1,1,1 + * max : 9,9,9,9, 9,9,9,9 + * out : 1,2,9,9, 1,9,9,9 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Set each element of vector between 0 and 255 + * Arguments : Inputs - _in + * Outputs - out + * Retrun 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; + + out = __lsx_vmaxi_h(_in, 0); + out = __lsx_vsat_hu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Set each element of vector between 0 and 255 + * Arguments : Inputs - _in + * Outputs - out + * Retrun 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; + + out = __lsx_vmaxi_w(_in, 0); + out = __lsx_vsat_wu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Swap two variables + * Arguments : Inputs - _in0, _in1 + * Outputs - _in0, _in1 (in-place) + * Details : Swapping of two input variables using xor + * Example : LSX_SWAP(_in0, _in1) + * _in0 : 1,2,3,4 + * _in1 : 5,6,7,8 + * _in0(out) : 5,6,7,8 + * _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); \ +} \ + +/* + * ============================================================================= + * Description : Transpose 4x4 block with word elements in vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : + * Example : + * 1, 2, 3, 4 1, 5, 9,13 + * 5, 6, 7, 8 to 2, 6,10,14 + * 9,10,11,12 =====> 3, 7,11,15 + * 13,14,15,16 4, 8,12,16 + * ============================================================================= + */ +#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); \ + _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. + * 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 + * _in2 : 20,21,22,23,24,25,26,27, 00,00,00,00,00,00,00,00 + * _in3 : 30,31,32,33,34,35,36,37, 00,00,00,00,00,00,00,00 + * _in4 : 40,41,42,43,44,45,46,47, 00,00,00,00,00,00,00,00 + * _in5 : 50,51,52,53,54,55,56,57, 00,00,00,00,00,00,00,00 + * _in6 : 60,61,62,63,64,65,66,67, 00,00,00,00,00,00,00,00 + * _in7 : 70,71,72,73,74,75,76,77, 00,00,00,00,00,00,00,00 + * + * _ out0 : 00,10,20,30,40,50,60,70, 00,00,00,00,00,00,00,00 + * _ out1 : 01,11,21,31,41,51,61,71, 00,00,00,00,00,00,00,00 + * _ out2 : 02,12,22,32,42,52,62,72, 00,00,00,00,00,00,00,00 + * _ out3 : 03,13,23,33,43,53,63,73, 00,00,00,00,00,00,00,00 + * _ out4 : 04,14,24,34,44,54,64,74, 00,00,00,00,00,00,00,00 + * _ out5 : 05,15,25,35,45,55,65,75, 00,00,00,00,00,00,00,00 + * _ out6 : 06,16,26,36,46,56,66,76, 00,00,00,00,00,00,00,00 + * _ 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); \ +} + +/* + * ============================================================================= + * 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 : + * Example : + * 00,01,02,03,04,05,06,07 00,10,20,30,40,50,60,70 + * 10,11,12,13,14,15,16,17 01,11,21,31,41,51,61,71 + * 20,21,22,23,24,25,26,27 02,12,22,32,42,52,62,72 + * 30,31,32,33,34,35,36,37 to 03,13,23,33,43,53,63,73 + * 40,41,42,43,44,45,46,47 ======> 04,14,24,34,44,54,64,74 + * 50,51,52,53,54,55,56,57 05,15,25,35,45,55,65,75 + * 60,61,62,63,64,65,66,67 06,16,26,36,46,56,66,76 + * 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); \ +} + +/* + * ============================================================================= + * Description : Transpose input 8x4 byte block into 4x8 + * 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. + * 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 + * _in2 : 20,21,22,23,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in3 : 30,31,32,33,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in4 : 40,41,42,43,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in5 : 50,51,52,53,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in6 : 60,61,62,63,00,00,00,00, 00,00,00,00,00,00,00,00 + * _in7 : 70,71,72,73,00,00,00,00, 00,00,00,00,00,00,00,00 + * + * _out0 : 00,10,20,30,40,50,60,70, 00,00,00,00,00,00,00,00 + * _out1 : 01,11,21,31,41,51,61,71, 00,00,00,00,00,00,00,00 + * _out2 : 02,12,22,32,42,52,62,72, 00,00,00,00,00,00,00,00 + * _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); \ +} + +/* + * ============================================================================= + * Description : Transpose 16x8 block with byte elements in vectors + * Arguments : Inputs - in0, in1, in2, in3, in4, in5, in6, in7, in8 + * in9, in10, in11, in12, in13, in14, in15 + * Outputs - out0, out1, out2, out3, out4, out5, out6, out7 + * Details : + * Example : + * 000,001,002,003,004,005,006,007 + * 008,009,010,011,012,013,014,015 + * 016,017,018,019,020,021,022,023 + * 024,025,026,027,028,029,030,031 + * 032,033,034,035,036,037,038,039 + * 040,041,042,043,044,045,046,047 000,008,...,112,120 + * 048,049,050,051,052,053,054,055 001,009,...,113,121 + * 056,057,058,059,060,061,062,063 to 002,010,...,114,122 + * 064,068,066,067,068,069,070,071 =====> 003,011,...,115,123 + * 072,073,074,075,076,077,078,079 004,012,...,116,124 + * 080,081,082,083,084,085,086,087 005,013,...,117,125 + * 088,089,090,091,092,093,094,095 006,014,...,118,126 + * 096,097,098,099,100,101,102,103 007,015,...,119,127 + * 104,105,106,107,108,109,110,111 + * 112,113,114,115,116,117,118,119 + * 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); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 4 input vectors + * Arguments : Inputs - in0, in1, in2, in3 + * Outputs - out0, out1, out2, out3 + * Details : Butterfly operation + * Example : + * out0 = in0 + in3; + * out1 = in1 + in2; + * out2 = in1 - in2; + * out3 = in0 - in3; + * ============================================================================= + */ +#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); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 8 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, ~ + * Outputs - _out0, _out1, _out2, _out3, ~ + * Details : Butterfly operation + * Example : + * _out0 = _in0 + _in7; + * _out1 = _in1 + _in6; + * _out2 = _in2 + _in5; + * _out3 = _in3 + _in4; + * _out4 = _in3 - _in4; + * _out5 = _in2 - _in5; + * _out6 = _in1 - _in6; + * _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_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_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 + +#ifdef __loongarch_asx +#include +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed 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 out vector + * 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; + + out = __lasx_xvmulwev_h_bu(in_h, in_l); + out = __lasx_xvmaddwod_h_bu(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed 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. + * Then this iniplication 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; + + out = __lasx_xvmulwev_h_b(in_h, in_l); + out = __lasx_xvmaddwod_h_b(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Then this multiplied results of adjacent odd-even elements + * are added to the out vector. + * Example : out = __lasx_xvdp2_w_h(in_h, in_l) + * 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 : 22,38,38,22, 22,38,38,22 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Dot product of word vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Retrun 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. + * 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; + + out = __lasx_xvmulwev_d_w(in_h, in_l); + out = __lasx_xvmaddwod_d_w(out, in_h, in_l); + return out; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. unsigned word. + * Multiplication result 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_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; +} + +/* + * ============================================================================= + * Description : Dot product & addition of byte vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Retrun 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. + * 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_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; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - per RTYPE + * Details : Signed halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added to the in_c vector. + * Example : out = __lasx_xvdp2add_w_h(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 __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; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * unsigned halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result 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_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; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Unsigned halfword elements from in_h are multiplied with + * signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result 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_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; +} + +/* + * ============================================================================= + * Description : Vector Unsigned Dot Product and Subtract + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed 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. + * Multiplication result of adjacent odd-even elements + * are added together and subtracted from double width elements + * in_c vector. + * 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; + + 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; +} + +/* + * ============================================================================= + * Description : Vector Signed Dot Product and Subtract + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are multiplied with + * Signed halfword elements from in_l producing a result + * twice the size of input i.e. signed word. + * Multiplication result of adjacent odd-even elements + * are added together and subtracted from double width elements + * in_c vector. + * Example : out = __lasx_xvdp2sub_w_h(in_c, in_h, in_l) + * in_c : 0,0,0,0, 0,0,0,0 + * in_h : 3,1,3,0, 0,0,0,1, 0,0,1,1, 0,0,0,1 + * in_l : 2,1,1,0, 1,0,0,0, 0,0,1,0, 1,0,0,1 + * 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; + + 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; +} + +/* + * ============================================================================= + * Description : Dot product of halfword vector elements + * Arguments : Inputs - in_h, in_l + * Output - out + * Return Type - signed word + * Details : Signed halfword elements from in_h are iniplied 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 + * 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 + * in_l : -2,1,1,0, 1,0,0,0, 0,0,1, 0, 1,0,0,1 + * out : -2,0,1,1 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : The high half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * higher half of the two-fold sign extension (signed byte + * to signed halfword) and stored to the out vector. + * 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; + + out = __lasx_xvilvh_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The high half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * higher half of the two-fold sign extension (signed halfword + * to signed word) and stored to the out vector. + * Example : out = __lasx_xvaddwh_w_h(in_h, in_l) + * in_h : 3, 0,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 1,0,1, 0, 1,0,0,1 + * out : 1,0,0,-1, 1,0,0, 2 + * ============================================================================= + */ + 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; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * lower half of the two-fold sign extension (signed byte + * to signed halfword) and stored to the out vector. + * 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; + + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_h_b(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are added after the + * lower half of the two-fold sign extension (signed halfword + * to signed word) and stored to the out vector. + * Example : out = __lasx_xvaddwl_w_h(in_h, in_l) + * in_h : 3, 0,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 1,0,1, 0, 1,0,0,1 + * out : 5,-1,4,2, 1,0,2,-1 + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The out vector and the out vector are added after the + * lower half of the two-fold zero extension (unsigned byte + * to unsigned halfword) and stored to the out vector. + * 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; + + out = __lasx_xvilvl_b(in_h, in_l); + out = __lasx_xvhaddw_hu_bu(out, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_l vector after double zero extension (unsigned byte to + * signed halfword),added to the in_h vector. + * 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; + + out = __lasx_xvsllwil_hu_bu(in_l, 0); + out = __lasx_xvadd_h(in_h, out); + return out; +} + +/* + * ============================================================================= + * Description : The low half of the vector elements are expanded and + * added after being doubled. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_l vector after double sign extension (signed halfword to + * signed word), added to the in_h vector. + * Example : out = __lasx_xvaddw_w_w_h(in_h, in_l) + * in_h : 0, 1,0,0, -1,0,0,1, + * in_l : 2,-1,1,2, 1,0,0,0, 0,0,1,0, 1,0,0,1, + * 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; + + out = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvadd_w(in_h, out); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication and addition calculation after expansion + * of the lower half of the vector. + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed halfword + * to signed word), and the result is added to the vector in_c, + * then stored to the out vector. + * Example : out = __lasx_xvmaddwl_w_h(in_c, in_h, in_l) + * in_c : 1,2,3,4, 5,6,7,8 + * in_h : 1,2,3,4, 1,2,3,4, 5,6,7,8, 5,6,7,8 + * in_l : 200, 300, 400, 500, 2000, 3000, 4000, 5000, + * -200,-300,-400,-500, -2000,-3000,-4000,-5000 + * 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; + + 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; +} + +/* + * ============================================================================= + * Description : Multiplication and addition calculation after expansion + * of the higher half of the vector. + * Arguments : Inputs - in_c, in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the higher half of the two-fold sign extension (signed + * halfword to signed word), and the result is added to + * the vector in_c, then stored to the out vector. + * 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; + + 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; +} + +/* + * ============================================================================= + * Description : Multiplication calculation after expansion of the lower + * half of the vector. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed + * halfword to signed word), then stored to the out vector. + * Example : out = __lasx_xvmulwl_w_h(in_h, in_l) + * in_h : 3,-1,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 0,0,1, 0, 1,0,0,1 + * 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; + + tmp0 = __lasx_xvsllwil_w_h(in_h, 0); + tmp1 = __lasx_xvsllwil_w_h(in_l, 0); + out = __lasx_xvmul_w(tmp0, tmp1); + return out; +} + +/* + * ============================================================================= + * Description : Multiplication calculation after expansion of the lower + * half of the vector. + * Arguments : Inputs - in_h, in_l + * Output - out + * Details : The in_h vector and the in_l vector are multiplied after + * the lower half of the two-fold sign extension (signed + * halfword to signed word), then stored to the out vector. + * Example : out = __lasx_xvmulwh_w_h(in_h, in_l) + * in_h : 3,-1,3,0, 0,0,0,-1, 0,0,1,-1, 0,0,0,1 + * in_l : 2,-1,1,2, 1,0,0, 0, 0,0,1, 0, 1,0,0,1 + * 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; + + 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. + * 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. + * 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, + * ============================================================================= + */ +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; +} + +/* + * ============================================================================= + * Description : Clip all halfword elements of input vector between min & max + * out = ((in) < (min)) ? (min) : (((in) > (max)) ? (max) : (in)) + * Arguments : Inputs - in (input vector) + * - min (min threshold) + * - max (max threshold) + * Outputs - in (output vector with clipped elements) + * Return Type - signed halfword + * Example : out = __lasx_xvclip_h(in, min, max) + * in : -8,2,280,249, -8,255,280,249, 4,4,4,4, 5,5,5,5 + * min : 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1 + * max : 9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9 + * 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; + + out = __lasx_xvmax_h(min, in); + out = __lasx_xvmin_h(max, out); + return out; +} + +/* + * ============================================================================= + * Description : Clip all signed halfword elements of input vector + * between 0 & 255 + * Arguments : Inputs - in (input vector) + * Outputs - out (output vector with clipped elements) + * Return Type - signed halfword + * Example : See out = __lasx_xvclip255_w(in) + * ============================================================================= + */ +static inline __m256i __lasx_xvclip255_h(__m256i in) +{ + __m256i out; + + out = __lasx_xvmaxi_h(in, 0); + out = __lasx_xvsat_hu(out, 7); + return out; +} + +/* + * ============================================================================= + * Description : Clip all signed word elements of input vector + * between 0 & 255 + * Arguments : Inputs - in (input vector) + * Output - out (output vector with clipped elements) + * Return Type - signed word + * Example : out = __lasx_xvclip255_w(in) + * in : -8,255,280,249, -8,255,280,249 + * out : 0,255,255,249, 0,255,255,249 + * ============================================================================= + */ +static inline __m256i __lasx_xvclip255_w(__m256i in) +{ + __m256i 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_*. + * Arguments : Inputs - in, idx + * Output - out + * Details : Idx element value from in vector is replicated to all + * elements in out vector. + * Valid index range for halfword operation is 0-7 + * Example : out = __lasx_xvsplati_l_h(in, idx) + * in : 20,10,11,12, 13,14,15,16, 0,0,2,0, 0,0,0,0 + * idx : 0x02 + * 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; + + 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_*. + * Arguments : Inputs - in, idx + * Output - out + * Details : Idx element value from in vector is replicated to all + * elements in out vector. + * Valid index range for halfword operation is 0-7 + * Example : out = __lasx_xvsplati_h_h(in, idx) + * in : 20,10,11,12, 13,14,15,16, 0,2,0,0, 0,0,0,0 + * idx : 0x09 + * 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; + + 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 + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Example : LASX_TRANSPOSE4x4_D + * _in0 : 1,2,3,4 + * _in1 : 1,2,3,4 + * _in2 : 1,2,3,4 + * _in3 : 1,2,3,4 + * + * _out0 : 1,1,1,1 + * _out1 : 2,2,2,2 + * _out2 : 3,3,3,3 + * _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); \ +} + +/* + * ============================================================================= + * 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 + * Example : LASX_TRANSPOSE8x8_W + * _in0 : 1,2,3,4,5,6,7,8 + * _in1 : 2,2,3,4,5,6,7,8 + * _in2 : 3,2,3,4,5,6,7,8 + * _in3 : 4,2,3,4,5,6,7,8 + * _in4 : 5,2,3,4,5,6,7,8 + * _in5 : 6,2,3,4,5,6,7,8 + * _in6 : 7,2,3,4,5,6,7,8 + * _in7 : 8,2,3,4,5,6,7,8 + * + * _out0 : 1,2,3,4,5,6,7,8 + * _out1 : 2,2,2,2,2,2,2,2 + * _out2 : 3,3,3,3,3,3,3,3 + * _out3 : 4,4,4,4,4,4,4,4 + * _out4 : 5,5,5,5,5,5,5,5 + * _out5 : 6,6,6,6,6,6,6,6 + * _out6 : 7,7,7,7,7,7,7,7 + * _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); \ +} + +/* + * ============================================================================= + * Description : Transpose input 16x8 byte block + * 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. + * 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); \ +} + +/* + * ============================================================================= + * Description : Transpose input 16x8 byte block + * 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. + * 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 + * _in2 : 3,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in3 : 4,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in4 : 5,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in5 : 6,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in6 : 7,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in7 : 8,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in8 : 9,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in9 : 1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in10 : 0,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in11 : 2,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in12 : 3,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in13 : 7,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in14 : 5,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * _in15 : 6,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0 + * + * _out0 : 1,2,3,4,5,6,7,8,9,1,0,2,3,7,5,6 + * _out1 : 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 + * _out2 : 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 + * _out3 : 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 + * _out4 : 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 + * _out5 : 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6 + * _out6 : 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + * _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); \ +} + +/* + * ============================================================================= + * Description : Transpose 4x4 block with halfword elements in vectors + * 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. + * 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); \ +} + +/* + * ============================================================================= + * 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) + * 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); \ +} + +/* + * ============================================================================= + * 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. + * 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 + * _in2 : 8,2,3,4, 5,6,7,8, 8,2,3,4, 5,6,7,8 + * _in3 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in4 : 9,2,3,4, 5,6,7,8, 9,2,3,4, 5,6,7,8 + * _in5 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in6 : 1,2,3,4, 5,6,7,8, 1,2,3,4, 5,6,7,8 + * _in7 : 9,2,3,4, 5,6,7,8, 9,2,3,4, 5,6,7,8 + * + * _out0 : 1,8,8,1, 9,1,1,9, 1,8,8,1, 9,1,1,9 + * _out1 : 2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2 + * _out2 : 3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3 + * _out3 : 4,4,4,4, 4,4,4,4, 4,4,4,4, 4,4,4,4 + * _out4 : 5,5,5,5, 5,5,5,5, 5,5,5,5, 5,5,5,5 + * _out5 : 6,6,6,6, 6,6,6,6, 6,6,6,6, 6,6,6,6 + * _out6 : 7,7,7,7, 7,7,7,7, 7,7,7,7, 7,7,7,7 + * _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); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 4 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3 + * Outputs - _out0, _out1, _out2, _out3 + * Details : Butterfly operation + * Example : LASX_BUTTERFLY_4 + * _out0 = _in0 + _in3; + * _out1 = _in1 + _in2; + * _out2 = _in1 - _in2; + * _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); \ +} + +/* + * ============================================================================= + * Description : Butterfly of 8 input vectors + * Arguments : Inputs - _in0, _in1, _in2, _in3, ~ + * Outputs - _out0, _out1, _out2, _out3, ~ + * Details : Butterfly operation + * Example : LASX_BUTTERFLY_8 + * _out0 = _in0 + _in7; + * _out1 = _in1 + _in6; + * _out2 = _in2 + _in5; + * _out3 = _in3 + _in4; + * _out4 = _in3 - _in4; + * _out5 = _in2 - _in5; + * _out6 = _in1 - _in6; + * _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_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_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 + +/* + * ============================================================================= + * Description : Print out elements in vector. + * Arguments : Inputs - RTYPE, _element_num, _in0, _enter + * Outputs - + * Details : Print out '_element_num' elements in 'RTYPE' vector '_in0', if + * '_enter' is TRUE, prefix "\nVP:" will be added first. + * Example : VECT_PRINT(v4i32,4,in0,1); // in0: 1,2,3,4 + * 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]); \ +} + +#endif /* LOONGSON_INTRINSICS_H */ +#endif /* AVUTIL_LOONGARCH_LOONGSON_INTRINSICS_H */ diff --git a/libavutil/mathematics.h b/libavutil/mathematics.h index 54901800ba..64d4137a60 100644 --- a/libavutil/mathematics.h +++ b/libavutil/mathematics.h @@ -134,6 +134,7 @@ int64_t av_rescale(int64_t a, int64_t b, int64_t c) av_const; * * The operation is mathematically equivalent to `a * b / c`, but writing that * directly can overflow, and does not support different rounding methods. + * If the result is not representable then INT64_MIN is returned. * * @see av_rescale(), av_rescale_q(), av_rescale_q_rnd() */ diff --git a/libavutil/objc.h b/libavutil/objc.h new file mode 100644 index 0000000000..0db993f716 --- /dev/null +++ b/libavutil/objc.h @@ -0,0 +1,32 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_OBJC_H +#define AVUTIL_OBJC_H + +#include + +static inline void ff_objc_release(NSObject **obj) +{ + if (*obj) { + [*obj release]; + *obj = nil; + } +} + +#endif /* AVUTIL_OBJC_H */ diff --git a/libavutil/opt.c b/libavutil/opt.c index c7001dbcd3..d951edca9d 100644 --- a/libavutil/opt.c +++ b/libavutil/opt.c @@ -920,7 +920,10 @@ int av_opt_get_int(void *obj, const char *name, int search_flags, int64_t *out_v if ((ret = get_number(obj, name, NULL, &num, &den, &intnum, search_flags)) < 0) return ret; - *out_val = num * intnum / den; + if (num == den) + *out_val = intnum; + else + *out_val = num * intnum / den; return 0; } @@ -1170,7 +1173,7 @@ static void opt_list(void *obj, void *av_log_obj, const char *unit, av_log(av_log_obj, AV_LOG_INFO, " %-15s ", opt->name); else av_log(av_log_obj, AV_LOG_INFO, " %s%-17s ", - (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? "" : "-", + (opt->flags & AV_OPT_FLAG_FILTERING_PARAM) ? " " : "-", opt->name); switch (opt->type) { diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c index 7f678cd85a..94e88e0a79 100644 --- a/libavutil/parseutils.c +++ b/libavutil/parseutils.c @@ -102,6 +102,7 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "wsxga", 1600,1024 }, { "wuxga", 1920,1200 }, { "woxga", 2560,1600 }, + { "wqhd", 2560,1440 }, { "wqsxga", 3200,2048 }, { "wquxga", 3840,2400 }, { "whsxga", 6400,4096 }, @@ -111,6 +112,7 @@ static const VideoSizeAbbr video_size_abbrs[] = { { "hd480", 852, 480 }, { "hd720", 1280, 720 }, { "hd1080", 1920,1080 }, + { "quadhd", 2560,1440 }, { "2k", 2048,1080 }, /* Digital Cinema System Specification */ { "2kdci", 2048,1080 }, { "2kflat", 1998,1080 }, diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 69cb198646..727d7540b3 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -2393,6 +2393,102 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { .name = "vulkan", .flags = AV_PIX_FMT_FLAG_HWACCEL, }, + [AV_PIX_FMT_P210BE] = { + .name = "p210be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P210LE] = { + .name = "p210le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P410BE] = { + .name = "p410be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P410LE] = { + .name = "p410le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 6, 10 }, /* Y */ + { 1, 4, 0, 6, 10 }, /* U */ + { 1, 4, 2, 6, 10 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P216BE] = { + .name = "p216be", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P216LE] = { + .name = "p216le", + .nb_components = 3, + .log2_chroma_w = 1, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, + [AV_PIX_FMT_P416BE] = { + .name = "p416be", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR | AV_PIX_FMT_FLAG_BE, + }, + [AV_PIX_FMT_P416LE] = { + .name = "p416le", + .nb_components = 3, + .log2_chroma_w = 0, + .log2_chroma_h = 0, + .comp = { + { 0, 2, 0, 0, 16 }, /* Y */ + { 1, 4, 0, 0, 16 }, /* U */ + { 1, 4, 2, 0, 16 }, /* V */ + }, + .flags = AV_PIX_FMT_FLAG_PLANAR, + }, }; static const char * const color_range_names[] = { diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 53bdecfcb7..02e355eb4d 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -352,6 +352,19 @@ enum AVPixelFormat { AV_PIX_FMT_X2RGB10BE, ///< packed RGB 10:10:10, 30bpp, (msb)2X 10R 10G 10B(lsb), big-endian, X=unused/undefined AV_PIX_FMT_X2BGR10LE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), little-endian, X=unused/undefined AV_PIX_FMT_X2BGR10BE, ///< packed BGR 10:10:10, 30bpp, (msb)2X 10B 10G 10R(lsb), big-endian, X=unused/undefined + + AV_PIX_FMT_P210BE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, big-endian + AV_PIX_FMT_P210LE, ///< interleaved chroma YUV 4:2:2, 20bpp, data in the high bits, little-endian + + AV_PIX_FMT_P410BE, ///< interleaved chroma YUV 4:4:4, 30bpp, data in the high bits, big-endian + 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_P416BE, ///< interleaved chroma YUV 4:4:4, 48bpp, big-endian + AV_PIX_FMT_P416LE, ///< interleaved chroma YUV 4:4:4, 48bpp, little-endian + AV_PIX_FMT_NB ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -444,6 +457,11 @@ enum AVPixelFormat { #define AV_PIX_FMT_X2RGB10 AV_PIX_FMT_NE(X2RGB10BE, X2RGB10LE) #define AV_PIX_FMT_X2BGR10 AV_PIX_FMT_NE(X2BGR10BE, X2BGR10LE) +#define AV_PIX_FMT_P210 AV_PIX_FMT_NE(P210BE, P210LE) +#define AV_PIX_FMT_P410 AV_PIX_FMT_NE(P410BE, P410LE) +#define AV_PIX_FMT_P216 AV_PIX_FMT_NE(P216BE, P216LE) +#define AV_PIX_FMT_P416 AV_PIX_FMT_NE(P416BE, P416LE) + /** * Chromaticity coordinates of the source primaries. * These values match the ones defined by ISO/IEC 23091-2_2019 subclause 8.1 and ITU-T H.273. diff --git a/libavutil/tests/cpu.c b/libavutil/tests/cpu.c index c853371fb3..5bec742b2b 100644 --- a/libavutil/tests/cpu.c +++ b/libavutil/tests/cpu.c @@ -77,6 +77,10 @@ static const struct { { AV_CPU_FLAG_BMI2, "bmi2" }, { AV_CPU_FLAG_AESNI, "aesni" }, { AV_CPU_FLAG_AVX512, "avx512" }, + { AV_CPU_FLAG_SLOW_GATHER, "slowgather" }, +#elif ARCH_LOONGARCH + { AV_CPU_FLAG_LSX, "lsx" }, + { AV_CPU_FLAG_LASX, "lasx" }, #endif { 0 } }; diff --git a/libavutil/tests/fifo.c b/libavutil/tests/fifo.c index 8a550e088b..a17d913233 100644 --- a/libavutil/tests/fifo.c +++ b/libavutil/tests/fifo.c @@ -30,14 +30,6 @@ int main(void) 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"); - /* peek_at at FIFO */ n = av_fifo_size(fifo) / sizeof(int); for (i = 0; i < n; i++) { diff --git a/libavutil/tests/twofish.c b/libavutil/tests/twofish.c index 74e0926eaf..7e8b129230 100644 --- a/libavutil/tests/twofish.c +++ b/libavutil/tests/twofish.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) }; uint8_t temp[32], iv[16], rpt[32] = {0}; const int kbits[3] = {128, 192, 256}; - int i, j, err = 0; + int i, j, k, err = 0; struct AVTWOFISH *cs; cs = av_twofish_alloc(); if (!cs) @@ -70,10 +70,19 @@ int main(int argc, char *argv[]) memcpy(Key+16,Key,(kbits[j]-128) >> 3); memcpy(Key,rpt,16); memcpy(rpt,temp,16); + av_twofish_crypt(cs, temp, temp, 1, NULL, 1); + for (k = 0; k < 16; k++) { + // Need to compare to Key here, because the plaintext comes + // from rpt but was moved over to Key. + if (Key[k] != temp[k]) { + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", k, Key[k], temp[k]); + err = 1; + } + } } for (i = 0; i < 16; i++) { - if (rct[3 + j][i] != temp[i]) { - av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], temp[i]); + if (rct[3 + j][i] != rpt[i]) { + av_log(NULL, AV_LOG_ERROR, "%d %02x %02x\n", i, rct[3 + j][i], rpt[i]); err = 1; } } diff --git a/libavutil/twofish.c b/libavutil/twofish.c index d84fa4f363..649b4bc41b 100644 --- a/libavutil/twofish.c +++ b/libavutil/twofish.c @@ -260,10 +260,10 @@ static void twofish_decrypt(AVTWOFISH *cs, uint8_t *dst, const uint8_t *src, uin P[3] ^= AV_RL32(iv + 12); memcpy(iv, src, 16); } - AV_WL32(dst, P[2]); - AV_WL32(dst + 4, P[3]); - AV_WL32(dst + 8, P[0]); - AV_WL32(dst + 12, P[1]); + AV_WL32(dst, P[0]); + AV_WL32(dst + 4, P[1]); + AV_WL32(dst + 8, P[2]); + AV_WL32(dst + 12, P[3]); } av_cold int av_twofish_init(AVTWOFISH *cs, const uint8_t *key, int key_bits) diff --git a/libavutil/version.h b/libavutil/version.h index 896e348d80..953aac9d94 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 57 -#define LIBAVUTIL_VERSION_MINOR 7 +#define LIBAVUTIL_VERSION_MINOR 18 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ @@ -105,18 +105,11 @@ * @{ */ -#ifndef FF_API_D2STR #define FF_API_D2STR (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_DECLARE_ALIGNED #define FF_API_DECLARE_ALIGNED (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_COLORSPACE_NAME #define FF_API_COLORSPACE_NAME (LIBAVUTIL_VERSION_MAJOR < 58) -#endif -#ifndef FF_API_AV_MALLOCZ_ARRAY #define FF_API_AV_MALLOCZ_ARRAY (LIBAVUTIL_VERSION_MAJOR < 58) -#endif +#define FF_API_FIFO_PEEK2 (LIBAVUTIL_VERSION_MAJOR < 58) /** * @} diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c new file mode 100644 index 0000000000..00df08b55e --- /dev/null +++ b/libavutil/vulkan.c @@ -0,0 +1,1405 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "avassert.h" + +#include "vulkan.h" +#include "vulkan_loader.h" + +#if CONFIG_LIBGLSLANG +#include "vulkan_glslang.c" +#elif CONFIG_LIBSHADERC +#include "vulkan_shaderc.c" +#endif + +/* Generic macro for creating contexts which need to keep their addresses + * if another context is created. */ +#define FN_CREATING(ctx, type, shortname, array, num) \ +static av_always_inline type *create_ ##shortname(ctx *dctx) \ +{ \ + type **array, *sctx = av_mallocz(sizeof(*sctx)); \ + if (!sctx) \ + return NULL; \ + \ + array = av_realloc_array(dctx->array, sizeof(*dctx->array), dctx->num + 1);\ + if (!array) { \ + av_free(sctx); \ + return NULL; \ + } \ + \ + dctx->array = array; \ + dctx->array[dctx->num++] = sctx; \ + \ + return sctx; \ +} + +const VkComponentMapping ff_comp_identity_map = { + .r = VK_COMPONENT_SWIZZLE_IDENTITY, + .g = VK_COMPONENT_SWIZZLE_IDENTITY, + .b = VK_COMPONENT_SWIZZLE_IDENTITY, + .a = VK_COMPONENT_SWIZZLE_IDENTITY, +}; + +/* Converts return values to strings */ +const char *ff_vk_ret2str(VkResult res) +{ +#define CASE(VAL) case VAL: return #VAL + switch (res) { + CASE(VK_SUCCESS); + CASE(VK_NOT_READY); + CASE(VK_TIMEOUT); + CASE(VK_EVENT_SET); + CASE(VK_EVENT_RESET); + CASE(VK_INCOMPLETE); + CASE(VK_ERROR_OUT_OF_HOST_MEMORY); + CASE(VK_ERROR_OUT_OF_DEVICE_MEMORY); + CASE(VK_ERROR_INITIALIZATION_FAILED); + CASE(VK_ERROR_DEVICE_LOST); + CASE(VK_ERROR_MEMORY_MAP_FAILED); + CASE(VK_ERROR_LAYER_NOT_PRESENT); + CASE(VK_ERROR_EXTENSION_NOT_PRESENT); + CASE(VK_ERROR_FEATURE_NOT_PRESENT); + CASE(VK_ERROR_INCOMPATIBLE_DRIVER); + CASE(VK_ERROR_TOO_MANY_OBJECTS); + CASE(VK_ERROR_FORMAT_NOT_SUPPORTED); + CASE(VK_ERROR_FRAGMENTED_POOL); + CASE(VK_ERROR_SURFACE_LOST_KHR); + CASE(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR); + CASE(VK_SUBOPTIMAL_KHR); + CASE(VK_ERROR_OUT_OF_DATE_KHR); + CASE(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR); + CASE(VK_ERROR_VALIDATION_FAILED_EXT); + CASE(VK_ERROR_INVALID_SHADER_NV); + CASE(VK_ERROR_OUT_OF_POOL_MEMORY); + CASE(VK_ERROR_INVALID_EXTERNAL_HANDLE); + CASE(VK_ERROR_NOT_PERMITTED_EXT); + default: return "Unknown error"; + } +#undef CASE +} + +void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues) +{ + switch (dev_family) { + case VK_QUEUE_GRAPHICS_BIT: + qf->queue_family = s->hwctx->queue_family_index; + qf->actual_queues = s->hwctx->nb_graphics_queues; + break; + case VK_QUEUE_COMPUTE_BIT: + qf->queue_family = s->hwctx->queue_family_comp_index; + qf->actual_queues = s->hwctx->nb_comp_queues; + break; + case VK_QUEUE_TRANSFER_BIT: + qf->queue_family = s->hwctx->queue_family_tx_index; + qf->actual_queues = s->hwctx->nb_tx_queues; + break; + case VK_QUEUE_VIDEO_ENCODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_encode_index; + qf->actual_queues = s->hwctx->nb_encode_queues; + break; + case VK_QUEUE_VIDEO_DECODE_BIT_KHR: + qf->queue_family = s->hwctx->queue_family_decode_index; + qf->actual_queues = s->hwctx->nb_decode_queues; + break; + default: + av_assert0(0); /* Should never happen */ + } + + if (!nb_queues) + qf->nb_queues = qf->actual_queues; + else + qf->nb_queues = nb_queues; + + return; +} + +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf) +{ + qf->cur_queue = (qf->cur_queue + 1) % qf->nb_queues; +} + +static int vk_alloc_mem(FFVulkanContext *s, VkMemoryRequirements *req, + VkMemoryPropertyFlagBits req_flags, void *alloc_extension, + VkMemoryPropertyFlagBits *mem_flags, VkDeviceMemory *mem) +{ + VkResult ret; + int index = -1; + FFVulkanFunctions *vk = &s->vkfn; + + VkMemoryAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + .pNext = alloc_extension, + }; + + /* Align if we need to */ + if (req_flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) + req->size = FFALIGN(req->size, s->props.limits.minMemoryMapAlignment); + + alloc_info.allocationSize = req->size; + + /* The vulkan spec requires memory types to be sorted in the "optimal" + * order, so the first matching type we find will be the best/fastest one */ + for (int i = 0; i < s->mprops.memoryTypeCount; i++) { + /* The memory type must be supported by the requirements (bitfield) */ + if (!(req->memoryTypeBits & (1 << i))) + continue; + + /* The memory type flags must include our properties */ + if ((s->mprops.memoryTypes[i].propertyFlags & req_flags) != req_flags) + continue; + + /* Found a suitable memory type */ + index = i; + break; + } + + if (index < 0) { + av_log(s, AV_LOG_ERROR, "No memory type found for flags 0x%x\n", + req_flags); + return AVERROR(EINVAL); + } + + alloc_info.memoryTypeIndex = index; + + ret = vk->AllocateMemory(s->hwctx->act_dev, &alloc_info, + s->hwctx->alloc, mem); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to allocate memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR(ENOMEM); + } + + *mem_flags |= s->mprops.memoryTypes[index].propertyFlags; + + return 0; +} + +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags) +{ + int err; + VkResult ret; + int use_ded_mem; + FFVulkanFunctions *vk = &s->vkfn; + + VkBufferCreateInfo buf_spawn = { + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = NULL, + .usage = usage, + .sharingMode = VK_SHARING_MODE_EXCLUSIVE, + .size = size, /* Gets FFALIGNED during alloc if host visible + but should be ok */ + }; + + VkBufferMemoryRequirementsInfo2 req_desc = { + .sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, + }; + VkMemoryDedicatedAllocateInfo ded_alloc = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, + .pNext = NULL, + }; + VkMemoryDedicatedRequirements ded_req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS, + }; + VkMemoryRequirements2 req = { + .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, + .pNext = &ded_req, + }; + + ret = vk->CreateBuffer(s->hwctx->act_dev, &buf_spawn, NULL, &buf->buf); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + req_desc.buffer = buf->buf; + + vk->GetBufferMemoryRequirements2(s->hwctx->act_dev, &req_desc, &req); + + /* In case the implementation prefers/requires dedicated allocation */ + use_ded_mem = ded_req.prefersDedicatedAllocation | + ded_req.requiresDedicatedAllocation; + if (use_ded_mem) + ded_alloc.buffer = buf->buf; + + err = vk_alloc_mem(s, &req.memoryRequirements, flags, + use_ded_mem ? &ded_alloc : (void *)ded_alloc.pNext, + &buf->flags, &buf->mem); + if (err) + return err; + + ret = vk->BindBufferMemory(s->hwctx->act_dev, buf->buf, buf->mem, 0); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to bind memory to buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], + int nb_buffers, int invalidate) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkMappedMemoryRange *inval_list = NULL; + int inval_count = 0; + + for (int i = 0; i < nb_buffers; i++) { + ret = vk->MapMemory(s->hwctx->act_dev, buf[i].mem, 0, + VK_WHOLE_SIZE, 0, (void **)&mem[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to map buffer memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + if (!invalidate) + return 0; + + for (int i = 0; i < nb_buffers; i++) { + const VkMappedMemoryRange ival_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = buf[i].mem, + .size = VK_WHOLE_SIZE, + }; + if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + inval_list = av_fast_realloc(s->scratch, &s->scratch_size, + (++inval_count)*sizeof(*inval_list)); + if (!inval_list) + return AVERROR(ENOMEM); + inval_list[inval_count - 1] = ival_buf; + } + + if (inval_count) { + ret = vk->InvalidateMappedMemoryRanges(s->hwctx->act_dev, inval_count, + inval_list); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to invalidate memory: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + return 0; +} + +int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, + int flush) +{ + int err = 0; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkMappedMemoryRange *flush_list = NULL; + int flush_count = 0; + + if (flush) { + for (int i = 0; i < nb_buffers; i++) { + const VkMappedMemoryRange flush_buf = { + .sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, + .memory = buf[i].mem, + .size = VK_WHOLE_SIZE, + }; + if (buf[i].flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) + continue; + flush_list = av_fast_realloc(s->scratch, &s->scratch_size, + (++flush_count)*sizeof(*flush_list)); + if (!flush_list) + return AVERROR(ENOMEM); + flush_list[flush_count - 1] = flush_buf; + } + } + + if (flush_count) { + ret = vk->FlushMappedMemoryRanges(s->hwctx->act_dev, flush_count, + flush_list); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to flush memory: %s\n", + ff_vk_ret2str(ret)); + err = AVERROR_EXTERNAL; /* We still want to try to unmap them */ + } + } + + for (int i = 0; i < nb_buffers; i++) + vk->UnmapMemory(s->hwctx->act_dev, buf[i].mem); + + return err; +} + +void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf) +{ + FFVulkanFunctions *vk = &s->vkfn; + + if (!buf || !s->hwctx) + return; + + vk->DeviceWaitIdle(s->hwctx->act_dev); + + if (buf->buf != VK_NULL_HANDLE) + vk->DestroyBuffer(s->hwctx->act_dev, buf->buf, s->hwctx->alloc); + if (buf->mem != VK_NULL_HANDLE) + vk->FreeMemory(s->hwctx->act_dev, buf->mem, s->hwctx->alloc); +} + +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage) +{ + VkPushConstantRange *pc; + + pl->push_consts = av_realloc_array(pl->push_consts, sizeof(*pl->push_consts), + pl->push_consts_num + 1); + if (!pl->push_consts) + return AVERROR(ENOMEM); + + pc = &pl->push_consts[pl->push_consts_num++]; + memset(pc, 0, sizeof(*pc)); + + pc->stageFlags = stage; + pc->offset = offset; + pc->size = size; + + return 0; +} + +FN_CREATING(FFVulkanContext, FFVkExecContext, exec_ctx, exec_ctx, exec_ctx_num) +int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf) +{ + VkResult ret; + FFVkExecContext *e; + FFVulkanFunctions *vk = &s->vkfn; + + VkCommandPoolCreateInfo cqueue_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, + .queueFamilyIndex = qf->queue_family, + }; + VkCommandBufferAllocateInfo cbuf_create = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = qf->nb_queues, + }; + + e = create_exec_ctx(s); + if (!e) + return AVERROR(ENOMEM); + + e->qf = qf; + + e->queues = av_mallocz(qf->nb_queues * sizeof(*e->queues)); + if (!e->queues) + return AVERROR(ENOMEM); + + e->bufs = av_mallocz(qf->nb_queues * sizeof(*e->bufs)); + if (!e->bufs) + return AVERROR(ENOMEM); + + /* Create command pool */ + ret = vk->CreateCommandPool(s->hwctx->act_dev, &cqueue_create, + s->hwctx->alloc, &e->pool); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command pool creation failure: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + cbuf_create.commandPool = e->pool; + + /* Allocate command buffer */ + ret = vk->AllocateCommandBuffers(s->hwctx->act_dev, &cbuf_create, e->bufs); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Command buffer alloc failure: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + for (int i = 0; i < qf->nb_queues; i++) { + FFVkQueueCtx *q = &e->queues[i]; + vk->GetDeviceQueue(s->hwctx->act_dev, qf->queue_family, + i % qf->actual_queues, &q->queue); + } + + *ctx = e; + + return 0; +} + +void ff_vk_discard_exec_deps(FFVkExecContext *e) +{ + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + for (int j = 0; j < q->nb_buf_deps; j++) + av_buffer_unref(&q->buf_deps[j]); + q->nb_buf_deps = 0; + + for (int j = 0; j < q->nb_frame_deps; j++) + av_frame_free(&q->frame_deps[j]); + q->nb_frame_deps = 0; + + e->sem_wait_cnt = 0; + e->sem_sig_cnt = 0; +} + +int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + VkCommandBufferBeginInfo cmd_start = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + + /* Create the fence and don't wait for it initially */ + if (!q->fence) { + VkFenceCreateInfo fence_spawn = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + }; + ret = vk->CreateFence(s->hwctx->act_dev, &fence_spawn, s->hwctx->alloc, + &q->fence); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to queue frame fence: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } else { + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); + } + + /* Discard queue dependencies */ + ff_vk_discard_exec_deps(e); + + ret = vk->BeginCommandBuffer(e->bufs[e->qf->cur_queue], &cmd_start); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to start command recoding: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e) +{ + return e->bufs[e->qf->cur_queue]; +} + +int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, + VkPipelineStageFlagBits in_wait_dst_flag) +{ + AVFrame **dst; + AVVkFrame *f = (AVVkFrame *)frame->data[0]; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + AVHWFramesContext *fc = (AVHWFramesContext *)frame->hw_frames_ctx->data; + int planes = av_pix_fmt_count_planes(fc->sw_format); + + for (int i = 0; i < planes; i++) { + e->sem_wait = av_fast_realloc(e->sem_wait, &e->sem_wait_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait)); + if (!e->sem_wait) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait_dst = av_fast_realloc(e->sem_wait_dst, &e->sem_wait_dst_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_dst)); + if (!e->sem_wait_dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait_val = av_fast_realloc(e->sem_wait_val, &e->sem_wait_val_alloc, + (e->sem_wait_cnt + 1)*sizeof(*e->sem_wait_val)); + if (!e->sem_wait_val) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig = av_fast_realloc(e->sem_sig, &e->sem_sig_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig)); + if (!e->sem_sig) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig_val = av_fast_realloc(e->sem_sig_val, &e->sem_sig_val_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val)); + if (!e->sem_sig_val) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_sig_val_dst = av_fast_realloc(e->sem_sig_val_dst, &e->sem_sig_val_dst_alloc, + (e->sem_sig_cnt + 1)*sizeof(*e->sem_sig_val_dst)); + if (!e->sem_sig_val_dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + e->sem_wait[e->sem_wait_cnt] = f->sem[i]; + e->sem_wait_dst[e->sem_wait_cnt] = in_wait_dst_flag; + e->sem_wait_val[e->sem_wait_cnt] = f->sem_value[i]; + e->sem_wait_cnt++; + + e->sem_sig[e->sem_sig_cnt] = f->sem[i]; + e->sem_sig_val[e->sem_sig_cnt] = f->sem_value[i] + 1; + e->sem_sig_val_dst[e->sem_sig_cnt] = &f->sem_value[i]; + e->sem_sig_cnt++; + } + + dst = av_fast_realloc(q->frame_deps, &q->frame_deps_alloc_size, + (q->nb_frame_deps + 1) * sizeof(*dst)); + if (!dst) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + + q->frame_deps = dst; + q->frame_deps[q->nb_frame_deps] = av_frame_clone(frame); + if (!q->frame_deps[q->nb_frame_deps]) { + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); + } + q->nb_frame_deps++; + + return 0; +} + +int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + VkTimelineSemaphoreSubmitInfo s_timeline_sem_info = { + .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, + .pWaitSemaphoreValues = e->sem_wait_val, + .pSignalSemaphoreValues = e->sem_sig_val, + .waitSemaphoreValueCount = e->sem_wait_cnt, + .signalSemaphoreValueCount = e->sem_sig_cnt, + }; + + VkSubmitInfo s_info = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .pNext = &s_timeline_sem_info, + + .commandBufferCount = 1, + .pCommandBuffers = &e->bufs[e->qf->cur_queue], + + .pWaitSemaphores = e->sem_wait, + .pWaitDstStageMask = e->sem_wait_dst, + .waitSemaphoreCount = e->sem_wait_cnt, + + .pSignalSemaphores = e->sem_sig, + .signalSemaphoreCount = e->sem_sig_cnt, + }; + + ret = vk->EndCommandBuffer(e->bufs[e->qf->cur_queue]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to finish command buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + ret = vk->QueueSubmit(q->queue, 1, &s_info, q->fence); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to submit command buffer: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + for (int i = 0; i < e->sem_sig_cnt; i++) + *e->sem_sig_val_dst[i] += 1; + + return 0; +} + +int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps) +{ + AVBufferRef **dst; + FFVkQueueCtx *q = &e->queues[e->qf->cur_queue]; + + if (!deps || !nb_deps) + return 0; + + dst = av_fast_realloc(q->buf_deps, &q->buf_deps_alloc_size, + (q->nb_buf_deps + nb_deps) * sizeof(*dst)); + if (!dst) + goto err; + + q->buf_deps = dst; + + for (int i = 0; i < nb_deps; i++) { + q->buf_deps[q->nb_buf_deps] = deps[i]; + if (!q->buf_deps[q->nb_buf_deps]) + goto err; + q->nb_buf_deps++; + } + + return 0; + +err: + ff_vk_discard_exec_deps(e); + return AVERROR(ENOMEM); +} + +FN_CREATING(FFVulkanContext, FFVkSampler, sampler, samplers, samplers_num) +FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, + int unnorm_coords, VkFilter filt) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkSamplerCreateInfo sampler_info = { + .sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, + .magFilter = filt, + .minFilter = sampler_info.magFilter, + .mipmapMode = unnorm_coords ? VK_SAMPLER_MIPMAP_MODE_NEAREST : + VK_SAMPLER_MIPMAP_MODE_LINEAR, + .addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, + .addressModeV = sampler_info.addressModeU, + .addressModeW = sampler_info.addressModeU, + .anisotropyEnable = VK_FALSE, + .compareOp = VK_COMPARE_OP_NEVER, + .borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + .unnormalizedCoordinates = unnorm_coords, + }; + + FFVkSampler *sctx = create_sampler(s); + if (!sctx) + return NULL; + + ret = vk->CreateSampler(s->hwctx->act_dev, &sampler_info, + s->hwctx->alloc, &sctx->sampler[0]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init sampler: %s\n", + ff_vk_ret2str(ret)); + return NULL; + } + + for (int i = 1; i < 4; i++) + sctx->sampler[i] = sctx->sampler[0]; + + return sctx; +} + +int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt) +{ + if (pix_fmt == AV_PIX_FMT_ABGR || pix_fmt == AV_PIX_FMT_BGRA || + pix_fmt == AV_PIX_FMT_RGBA || pix_fmt == AV_PIX_FMT_RGB24 || + pix_fmt == AV_PIX_FMT_BGR24 || pix_fmt == AV_PIX_FMT_RGB48 || + pix_fmt == AV_PIX_FMT_RGBA64 || pix_fmt == AV_PIX_FMT_RGB565 || + pix_fmt == AV_PIX_FMT_BGR565 || pix_fmt == AV_PIX_FMT_BGR0 || + pix_fmt == AV_PIX_FMT_0BGR || pix_fmt == AV_PIX_FMT_RGB0) + return 1; + return 0; +} + +const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pixfmt); + const int high = desc->comp[0].depth > 8; + return high ? "rgba16f" : "rgba8"; +} + +typedef struct ImageViewCtx { + VkImageView view; +} ImageViewCtx; + +static void destroy_imageview(void *opaque, uint8_t *data) +{ + FFVulkanContext *s = opaque; + FFVulkanFunctions *vk = &s->vkfn; + ImageViewCtx *iv = (ImageViewCtx *)data; + + vk->DestroyImageView(s->hwctx->act_dev, iv->view, s->hwctx->alloc); + av_free(iv); +} + +int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, + VkImageView *v, VkImage img, VkFormat fmt, + const VkComponentMapping map) +{ + int err; + AVBufferRef *buf; + FFVulkanFunctions *vk = &s->vkfn; + + VkImageViewCreateInfo imgview_spawn = { + .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, + .pNext = NULL, + .image = img, + .viewType = VK_IMAGE_VIEW_TYPE_2D, + .format = fmt, + .components = map, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .baseMipLevel = 0, + .levelCount = 1, + .baseArrayLayer = 0, + .layerCount = 1, + }, + }; + + ImageViewCtx *iv = av_mallocz(sizeof(*iv)); + + VkResult ret = vk->CreateImageView(s->hwctx->act_dev, &imgview_spawn, + s->hwctx->alloc, &iv->view); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Failed to create imageview: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + buf = av_buffer_create((uint8_t *)iv, sizeof(*iv), destroy_imageview, s, 0); + if (!buf) { + destroy_imageview(s, (uint8_t *)iv); + return AVERROR(ENOMEM); + } + + /* Add to queue dependencies */ + err = ff_vk_add_dep_exec_ctx(s, e, &buf, 1); + if (err) { + av_buffer_unref(&buf); + return err; + } + + *v = iv->view; + + return 0; +} + +FN_CREATING(FFVulkanPipeline, FFVkSPIRVShader, shader, shaders, shaders_num) +FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, + VkShaderStageFlags stage) +{ + FFVkSPIRVShader *shd = create_shader(pl); + if (!shd) + return NULL; + + av_bprint_init(&shd->src, 0, AV_BPRINT_SIZE_UNLIMITED); + + shd->shader.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shd->shader.stage = stage; + + shd->name = name; + + GLSLF(0, #version %i ,460); + GLSLC(0, #define IS_WITHIN(v1, v2) ((v1.x < v2.x) && (v1.y < v2.y)) ); + GLSLC(0, ); + + return shd; +} + +void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]) +{ + shd->local_size[0] = local_size[0]; + shd->local_size[1] = local_size[1]; + shd->local_size[2] = local_size[2]; + + av_bprintf(&shd->src, "layout (local_size_x = %i, " + "local_size_y = %i, local_size_z = %i) in;\n\n", + shd->local_size[0], shd->local_size[1], shd->local_size[2]); +} + +void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio) +{ + int line = 0; + const char *p = shd->src.str; + const char *start = p; + + AVBPrint buf; + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + + for (int i = 0; i < strlen(p); i++) { + if (p[i] == '\n') { + av_bprintf(&buf, "%i\t", ++line); + av_bprint_append_data(&buf, start, &p[i] - start + 1); + start = &p[i + 1]; + } + } + + av_log(ctx, prio, "Shader %s: \n%s", shd->name, buf.str); + av_bprint_finalize(&buf, NULL); +} + +int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, + const char *entrypoint) +{ + int err; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + VkShaderModuleCreateInfo shader_create; + uint8_t *spirv; + size_t spirv_size; + void *priv; + + shd->shader.pName = entrypoint; + + if (!s->spirv_compiler) { +#if CONFIG_LIBGLSLANG + s->spirv_compiler = ff_vk_glslang_init(); +#elif CONFIG_LIBSHADERC + s->spirv_compiler = ff_vk_shaderc_init(); +#else + return AVERROR(ENOSYS); +#endif + if (!s->spirv_compiler) + return AVERROR(ENOMEM); + } + + err = s->spirv_compiler->compile_shader(s->spirv_compiler, s, shd, &spirv, + &spirv_size, entrypoint, &priv); + if (err < 0) + return err; + + av_log(s, AV_LOG_VERBOSE, "Shader %s compiled! Size: %zu bytes\n", + shd->name, spirv_size); + + shader_create.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_create.pNext = NULL; + shader_create.codeSize = spirv_size; + shader_create.flags = 0; + shader_create.pCode = (void *)spirv; + + ret = vk->CreateShaderModule(s->hwctx->act_dev, &shader_create, NULL, + &shd->shader.module); + + s->spirv_compiler->free_shader(s->spirv_compiler, &priv); + + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to create shader module: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + return 0; +} + +static const struct descriptor_props { + size_t struct_size; /* Size of the opaque which updates the descriptor */ + const char *type; + int is_uniform; + int mem_quali; /* Can use a memory qualifier */ + int dim_needed; /* Must indicate dimension */ + int buf_content; /* Must indicate buffer contents */ +} descriptor_props[] = { + [VK_DESCRIPTOR_TYPE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE] = { sizeof(VkDescriptorImageInfo), "texture", 1, 0, 1, 0, }, + [VK_DESCRIPTOR_TYPE_STORAGE_IMAGE] = { sizeof(VkDescriptorImageInfo), "image", 1, 1, 1, 0, }, + [VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT] = { sizeof(VkDescriptorImageInfo), "subpassInput", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER] = { sizeof(VkDescriptorImageInfo), "sampler", 1, 0, 1, 0, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, + [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), NULL, 1, 0, 0, 1, }, + [VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC] = { sizeof(VkDescriptorBufferInfo), "buffer", 0, 1, 0, 1, }, + [VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER] = { sizeof(VkBufferView), "samplerBuffer", 1, 0, 0, 0, }, + [VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER] = { sizeof(VkBufferView), "imageBuffer", 1, 0, 0, 0, }, +}; + +int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, + int num, int only_print_to_shader) +{ + VkResult ret; + VkDescriptorSetLayout *layout; + FFVulkanFunctions *vk = &s->vkfn; + + if (only_print_to_shader) + goto print; + + pl->desc_layout = av_realloc_array(pl->desc_layout, sizeof(*pl->desc_layout), + pl->desc_layout_num + pl->qf->nb_queues); + if (!pl->desc_layout) + return AVERROR(ENOMEM); + + pl->desc_set_initialized = av_realloc_array(pl->desc_set_initialized, + sizeof(*pl->desc_set_initialized), + pl->descriptor_sets_num + 1); + if (!pl->desc_set_initialized) + return AVERROR(ENOMEM); + + pl->desc_set_initialized[pl->descriptor_sets_num] = 0; + layout = &pl->desc_layout[pl->desc_layout_num]; + + { /* Create descriptor set layout descriptions */ + VkDescriptorSetLayoutCreateInfo desc_create_layout = { 0 }; + VkDescriptorSetLayoutBinding *desc_binding; + + desc_binding = av_mallocz(sizeof(*desc_binding)*num); + if (!desc_binding) + return AVERROR(ENOMEM); + + for (int i = 0; i < num; i++) { + desc_binding[i].binding = i; + desc_binding[i].descriptorType = desc[i].type; + desc_binding[i].descriptorCount = FFMAX(desc[i].elems, 1); + desc_binding[i].stageFlags = desc[i].stages; + desc_binding[i].pImmutableSamplers = desc[i].sampler ? + desc[i].sampler->sampler : + NULL; + } + + desc_create_layout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + desc_create_layout.pBindings = desc_binding; + desc_create_layout.bindingCount = num; + + for (int i = 0; i < pl->qf->nb_queues; i++) { + ret = vk->CreateDescriptorSetLayout(s->hwctx->act_dev, &desc_create_layout, + s->hwctx->alloc, &layout[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor set " + "layout: %s\n", ff_vk_ret2str(ret)); + av_free(desc_binding); + return AVERROR_EXTERNAL; + } + } + + av_free(desc_binding); + } + + { /* Pool each descriptor by type and update pool counts */ + for (int i = 0; i < num; i++) { + int j; + for (j = 0; j < pl->pool_size_desc_num; j++) + if (pl->pool_size_desc[j].type == desc[i].type) + break; + if (j >= pl->pool_size_desc_num) { + pl->pool_size_desc = av_realloc_array(pl->pool_size_desc, + sizeof(*pl->pool_size_desc), + ++pl->pool_size_desc_num); + if (!pl->pool_size_desc) + return AVERROR(ENOMEM); + memset(&pl->pool_size_desc[j], 0, sizeof(VkDescriptorPoolSize)); + } + pl->pool_size_desc[j].type = desc[i].type; + pl->pool_size_desc[j].descriptorCount += FFMAX(desc[i].elems, 1)*pl->qf->nb_queues; + } + } + + { /* Create template creation struct */ + VkDescriptorUpdateTemplateCreateInfo *dt; + VkDescriptorUpdateTemplateEntry *des_entries; + + /* Freed after descriptor set initialization */ + des_entries = av_mallocz(num*sizeof(VkDescriptorUpdateTemplateEntry)); + if (!des_entries) + return AVERROR(ENOMEM); + + for (int i = 0; i < num; i++) { + des_entries[i].dstBinding = i; + des_entries[i].descriptorType = desc[i].type; + des_entries[i].descriptorCount = FFMAX(desc[i].elems, 1); + des_entries[i].dstArrayElement = 0; + des_entries[i].offset = ((uint8_t *)desc[i].updater) - (uint8_t *)s; + des_entries[i].stride = descriptor_props[desc[i].type].struct_size; + } + + pl->desc_template_info = av_realloc_array(pl->desc_template_info, + sizeof(*pl->desc_template_info), + pl->total_descriptor_sets + pl->qf->nb_queues); + if (!pl->desc_template_info) + return AVERROR(ENOMEM); + + dt = &pl->desc_template_info[pl->total_descriptor_sets]; + memset(dt, 0, sizeof(*dt)*pl->qf->nb_queues); + + for (int i = 0; i < pl->qf->nb_queues; i++) { + dt[i].sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO; + dt[i].templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; + dt[i].descriptorSetLayout = layout[i]; + dt[i].pDescriptorUpdateEntries = des_entries; + dt[i].descriptorUpdateEntryCount = num; + } + } + + pl->descriptor_sets_num++; + + pl->desc_layout_num += pl->qf->nb_queues; + pl->total_descriptor_sets += pl->qf->nb_queues; + +print: + /* Write shader info */ + for (int i = 0; i < num; i++) { + const struct descriptor_props *prop = &descriptor_props[desc[i].type]; + GLSLA("layout (set = %i, binding = %i", pl->descriptor_sets_num - 1, i); + + if (desc[i].mem_layout) + GLSLA(", %s", desc[i].mem_layout); + GLSLA(")"); + + if (prop->is_uniform) + GLSLA(" uniform"); + + if (prop->mem_quali && desc[i].mem_quali) + GLSLA(" %s", desc[i].mem_quali); + + if (prop->type) + GLSLA(" %s", prop->type); + + if (prop->dim_needed) + GLSLA("%iD", desc[i].dimensions); + + GLSLA(" %s", desc[i].name); + + if (prop->buf_content) + GLSLA(" {\n %s\n}", desc[i].buf_content); + else if (desc[i].elems > 0) + GLSLA("[%i]", desc[i].elems); + + GLSLA(";\n"); + } + GLSLA("\n"); + + return 0; +} + +void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + int set_id) +{ + FFVulkanFunctions *vk = &s->vkfn; + + /* If a set has never been updated, update all queues' sets. */ + if (!pl->desc_set_initialized[set_id]) { + for (int i = 0; i < pl->qf->nb_queues; i++) { + int idx = set_id*pl->qf->nb_queues + i; + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[idx], + pl->desc_template[idx], + s); + } + pl->desc_set_initialized[set_id] = 1; + return; + } + + set_id = set_id*pl->qf->nb_queues + pl->qf->cur_queue; + + vk->UpdateDescriptorSetWithTemplate(s->hwctx->act_dev, + pl->desc_set[set_id], + pl->desc_template[set_id], + s); +} + +void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, + VkShaderStageFlagBits stage, int offset, + size_t size, void *src) +{ + FFVulkanFunctions *vk = &s->vkfn; + + vk->CmdPushConstants(e->bufs[e->qf->cur_queue], e->bound_pl->pipeline_layout, + stage, offset, size, src); +} + +int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + pl->desc_staging = av_malloc(pl->descriptor_sets_num*sizeof(*pl->desc_staging)); + if (!pl->desc_staging) + return AVERROR(ENOMEM); + + { /* Init descriptor set pool */ + VkDescriptorPoolCreateInfo pool_create_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .poolSizeCount = pl->pool_size_desc_num, + .pPoolSizes = pl->pool_size_desc, + .maxSets = pl->total_descriptor_sets, + }; + + ret = vk->CreateDescriptorPool(s->hwctx->act_dev, &pool_create_info, + s->hwctx->alloc, &pl->desc_pool); + av_freep(&pl->pool_size_desc); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor set " + "pool: %s\n", ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Allocate descriptor sets */ + VkDescriptorSetAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = pl->desc_pool, + .descriptorSetCount = pl->total_descriptor_sets, + .pSetLayouts = pl->desc_layout, + }; + + pl->desc_set = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_set)); + if (!pl->desc_set) + return AVERROR(ENOMEM); + + ret = vk->AllocateDescriptorSets(s->hwctx->act_dev, &alloc_info, + pl->desc_set); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to allocate descriptor set: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Finally create the pipeline layout */ + VkPipelineLayoutCreateInfo spawn_pipeline_layout = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pSetLayouts = (VkDescriptorSetLayout *)pl->desc_staging, + .pushConstantRangeCount = pl->push_consts_num, + .pPushConstantRanges = pl->push_consts, + }; + + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) + pl->desc_staging[spawn_pipeline_layout.setLayoutCount++] = pl->desc_layout[i]; + + ret = vk->CreatePipelineLayout(s->hwctx->act_dev, &spawn_pipeline_layout, + s->hwctx->alloc, &pl->pipeline_layout); + av_freep(&pl->push_consts); + pl->push_consts_num = 0; + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init pipeline layout: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + { /* Descriptor template (for tightly packed descriptors) */ + VkDescriptorUpdateTemplateCreateInfo *dt; + + pl->desc_template = av_malloc(pl->total_descriptor_sets*sizeof(*pl->desc_template)); + if (!pl->desc_template) + return AVERROR(ENOMEM); + + /* Create update templates for the descriptor sets */ + for (int i = 0; i < pl->total_descriptor_sets; i++) { + dt = &pl->desc_template_info[i]; + dt->pipelineLayout = pl->pipeline_layout; + ret = vk->CreateDescriptorUpdateTemplate(s->hwctx->act_dev, + dt, s->hwctx->alloc, + &pl->desc_template[i]); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init descriptor " + "template: %s\n", ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + } + + /* Free the duplicated memory used for the template entries */ + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } + + av_freep(&pl->desc_template_info); + } + + return 0; +} + +FN_CREATING(FFVulkanContext, FFVulkanPipeline, pipeline, pipelines, pipelines_num) +FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf) +{ + FFVulkanPipeline *pl = create_pipeline(s); + if (pl) + pl->qf = qf; + + return pl; +} + +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + int i; + VkResult ret; + FFVulkanFunctions *vk = &s->vkfn; + + VkComputePipelineCreateInfo pipe = { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .layout = pl->pipeline_layout, + }; + + for (i = 0; i < pl->shaders_num; i++) { + if (pl->shaders[i]->shader.stage & VK_SHADER_STAGE_COMPUTE_BIT) { + pipe.stage = pl->shaders[i]->shader; + break; + } + } + if (i == pl->shaders_num) { + av_log(s, AV_LOG_ERROR, "Can't init compute pipeline, no shader\n"); + return AVERROR(EINVAL); + } + + ret = vk->CreateComputePipelines(s->hwctx->act_dev, VK_NULL_HANDLE, 1, &pipe, + s->hwctx->alloc, &pl->pipeline); + if (ret != VK_SUCCESS) { + av_log(s, AV_LOG_ERROR, "Unable to init compute pipeline: %s\n", + ff_vk_ret2str(ret)); + return AVERROR_EXTERNAL; + } + + pl->bind_point = VK_PIPELINE_BIND_POINT_COMPUTE; + + return 0; +} + +void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl) +{ + FFVulkanFunctions *vk = &s->vkfn; + + vk->CmdBindPipeline(e->bufs[e->qf->cur_queue], pl->bind_point, pl->pipeline); + + for (int i = 0; i < pl->descriptor_sets_num; i++) + pl->desc_staging[i] = pl->desc_set[i*pl->qf->nb_queues + pl->qf->cur_queue]; + + vk->CmdBindDescriptorSets(e->bufs[e->qf->cur_queue], pl->bind_point, + pl->pipeline_layout, 0, + pl->descriptor_sets_num, + (VkDescriptorSet *)pl->desc_staging, + 0, NULL); + + e->bound_pl = pl; +} + +static void free_exec_ctx(FFVulkanContext *s, FFVkExecContext *e) +{ + FFVulkanFunctions *vk = &s->vkfn; + + /* Make sure all queues have finished executing */ + for (int i = 0; i < e->qf->nb_queues; i++) { + FFVkQueueCtx *q = &e->queues[i]; + + if (q->fence) { + vk->WaitForFences(s->hwctx->act_dev, 1, &q->fence, VK_TRUE, UINT64_MAX); + vk->ResetFences(s->hwctx->act_dev, 1, &q->fence); + } + + /* Free the fence */ + if (q->fence) + vk->DestroyFence(s->hwctx->act_dev, q->fence, s->hwctx->alloc); + + /* Free buffer dependencies */ + for (int j = 0; j < q->nb_buf_deps; j++) + av_buffer_unref(&q->buf_deps[j]); + av_free(q->buf_deps); + + /* Free frame dependencies */ + for (int j = 0; j < q->nb_frame_deps; j++) + av_frame_free(&q->frame_deps[j]); + av_free(q->frame_deps); + } + + if (e->bufs) + vk->FreeCommandBuffers(s->hwctx->act_dev, e->pool, e->qf->nb_queues, e->bufs); + if (e->pool) + vk->DestroyCommandPool(s->hwctx->act_dev, e->pool, s->hwctx->alloc); + + av_freep(&e->bufs); + av_freep(&e->queues); + av_freep(&e->sem_sig); + av_freep(&e->sem_sig_val); + av_freep(&e->sem_sig_val_dst); + av_freep(&e->sem_wait); + av_freep(&e->sem_wait_dst); + av_freep(&e->sem_wait_val); + av_free(e); +} + +static void free_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl) +{ + FFVulkanFunctions *vk = &s->vkfn; + + for (int i = 0; i < pl->shaders_num; i++) { + FFVkSPIRVShader *shd = pl->shaders[i]; + av_bprint_finalize(&shd->src, NULL); + vk->DestroyShaderModule(s->hwctx->act_dev, shd->shader.module, + s->hwctx->alloc); + av_free(shd); + } + + vk->DestroyPipeline(s->hwctx->act_dev, pl->pipeline, s->hwctx->alloc); + vk->DestroyPipelineLayout(s->hwctx->act_dev, pl->pipeline_layout, + s->hwctx->alloc); + + for (int i = 0; i < pl->desc_layout_num; i++) { + if (pl->desc_template && pl->desc_template[i]) + vk->DestroyDescriptorUpdateTemplate(s->hwctx->act_dev, pl->desc_template[i], + s->hwctx->alloc); + if (pl->desc_layout && pl->desc_layout[i]) + vk->DestroyDescriptorSetLayout(s->hwctx->act_dev, pl->desc_layout[i], + s->hwctx->alloc); + } + + /* Also frees the descriptor sets */ + if (pl->desc_pool) + vk->DestroyDescriptorPool(s->hwctx->act_dev, pl->desc_pool, + s->hwctx->alloc); + + av_freep(&pl->desc_staging); + av_freep(&pl->desc_set); + av_freep(&pl->shaders); + av_freep(&pl->desc_layout); + av_freep(&pl->desc_template); + av_freep(&pl->desc_set_initialized); + av_freep(&pl->push_consts); + pl->push_consts_num = 0; + + /* Only freed in case of failure */ + av_freep(&pl->pool_size_desc); + if (pl->desc_template_info) { + for (int i = 0; i < pl->total_descriptor_sets; i += pl->qf->nb_queues) { + VkDescriptorUpdateTemplateCreateInfo *dt = &pl->desc_template_info[i]; + av_free((void *)dt->pDescriptorUpdateEntries); + } + av_freep(&pl->desc_template_info); + } + + av_free(pl); +} + +void ff_vk_uninit(FFVulkanContext *s) +{ + FFVulkanFunctions *vk = &s->vkfn; + + if (s->spirv_compiler) + s->spirv_compiler->uninit(&s->spirv_compiler); + + for (int i = 0; i < s->exec_ctx_num; i++) + free_exec_ctx(s, s->exec_ctx[i]); + av_freep(&s->exec_ctx); + + for (int i = 0; i < s->samplers_num; i++) { + vk->DestroySampler(s->hwctx->act_dev, s->samplers[i]->sampler[0], + s->hwctx->alloc); + av_free(s->samplers[i]); + } + av_freep(&s->samplers); + + for (int i = 0; i < s->pipelines_num; i++) + free_pipeline(s, s->pipelines[i]); + av_freep(&s->pipelines); + + av_freep(&s->scratch); + s->scratch_size = 0; + + av_buffer_unref(&s->device_ref); + av_buffer_unref(&s->frames_ref); +} diff --git a/libavutil/vulkan.h b/libavutil/vulkan.h new file mode 100644 index 0000000000..d1ea1e24fb --- /dev/null +++ b/libavutil/vulkan.h @@ -0,0 +1,422 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VULKAN_H +#define AVUTIL_VULKAN_H + +#include "pixdesc.h" +#include "bprint.h" +#include "hwcontext.h" +#include "vulkan_functions.h" +#include "hwcontext_vulkan.h" +#include "vulkan_loader.h" + +#define FF_VK_DEFAULT_USAGE_FLAGS (VK_IMAGE_USAGE_SAMPLED_BIT | \ + VK_IMAGE_USAGE_STORAGE_BIT | \ + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | \ + VK_IMAGE_USAGE_TRANSFER_DST_BIT) + +/* GLSL management macros */ +#define INDENT(N) INDENT_##N +#define INDENT_0 +#define INDENT_1 INDENT_0 " " +#define INDENT_2 INDENT_1 INDENT_1 +#define INDENT_3 INDENT_2 INDENT_1 +#define INDENT_4 INDENT_3 INDENT_1 +#define INDENT_5 INDENT_4 INDENT_1 +#define INDENT_6 INDENT_5 INDENT_1 +#define C(N, S) INDENT(N) #S "\n" +#define GLSLC(N, S) av_bprintf(&shd->src, C(N, S)) +#define GLSLA(...) av_bprintf(&shd->src, __VA_ARGS__) +#define GLSLF(N, S, ...) av_bprintf(&shd->src, C(N, S), __VA_ARGS__) +#define GLSLD(D) GLSLC(0, ); \ + av_bprint_append_data(&shd->src, D, strlen(D)); \ + GLSLC(0, ) + +/* Helper, pretty much every Vulkan return value needs to be checked */ +#define RET(x) \ + do { \ + if ((err = (x)) < 0) \ + goto fail; \ + } while (0) + +typedef struct FFVkSPIRVShader { + const char *name; /* Name for id/debugging purposes */ + AVBPrint src; + int local_size[3]; /* Compute shader workgroup sizes */ + VkPipelineShaderStageCreateInfo shader; +} FFVkSPIRVShader; + +typedef struct FFVkSPIRVCompiler { + void *priv; + int (*compile_shader)(struct FFVkSPIRVCompiler *ctx, void *avctx, + struct FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, void **opaque); + void (*free_shader)(struct FFVkSPIRVCompiler *ctx, void **opaque); + void (*uninit)(struct FFVkSPIRVCompiler **ctx); +} FFVkSPIRVCompiler; + +typedef struct FFVkSampler { + VkSampler sampler[4]; +} FFVkSampler; + +typedef struct FFVulkanDescriptorSetBinding { + const char *name; + VkDescriptorType type; + const char *mem_layout; /* Storage images (rgba8, etc.) and buffers (std430, etc.) */ + const char *mem_quali; /* readonly, writeonly, etc. */ + const char *buf_content; /* For buffers */ + uint32_t dimensions; /* Needed for e.g. sampler%iD */ + uint32_t elems; /* 0 - scalar, 1 or more - vector */ + VkShaderStageFlags stages; + FFVkSampler *sampler; /* Sampler to use for all elems */ + void *updater; /* Pointer to VkDescriptor*Info */ +} FFVulkanDescriptorSetBinding; + +typedef struct FFVkBuffer { + VkBuffer buf; + VkDeviceMemory mem; + VkMemoryPropertyFlagBits flags; +} FFVkBuffer; + +typedef struct FFVkQueueFamilyCtx { + int queue_family; + int nb_queues; + int cur_queue; + int actual_queues; +} FFVkQueueFamilyCtx; + +typedef struct FFVulkanPipeline { + FFVkQueueFamilyCtx *qf; + + VkPipelineBindPoint bind_point; + + /* Contexts */ + VkPipelineLayout pipeline_layout; + VkPipeline pipeline; + + /* Shaders */ + FFVkSPIRVShader **shaders; + int shaders_num; + + /* Push consts */ + VkPushConstantRange *push_consts; + int push_consts_num; + + /* Descriptors */ + VkDescriptorSetLayout *desc_layout; + VkDescriptorPool desc_pool; + VkDescriptorSet *desc_set; + void **desc_staging; + VkDescriptorSetLayoutBinding **desc_binding; + VkDescriptorUpdateTemplate *desc_template; + int *desc_set_initialized; + int desc_layout_num; + int descriptor_sets_num; + int total_descriptor_sets; + int pool_size_desc_num; + + /* Temporary, used to store data in between initialization stages */ + VkDescriptorUpdateTemplateCreateInfo *desc_template_info; + VkDescriptorPoolSize *pool_size_desc; +} FFVulkanPipeline; + +typedef struct FFVkQueueCtx { + VkFence fence; + VkQueue queue; + + /* Buffer dependencies */ + AVBufferRef **buf_deps; + int nb_buf_deps; + int buf_deps_alloc_size; + + /* Frame dependencies */ + AVFrame **frame_deps; + int nb_frame_deps; + int frame_deps_alloc_size; +} FFVkQueueCtx; + +typedef struct FFVkExecContext { + FFVkQueueFamilyCtx *qf; + + VkCommandPool pool; + VkCommandBuffer *bufs; + FFVkQueueCtx *queues; + + AVBufferRef ***deps; + int *nb_deps; + int *dep_alloc_size; + + FFVulkanPipeline *bound_pl; + + VkSemaphore *sem_wait; + int sem_wait_alloc; /* Allocated sem_wait */ + int sem_wait_cnt; + + uint64_t *sem_wait_val; + int sem_wait_val_alloc; + + VkPipelineStageFlagBits *sem_wait_dst; + int sem_wait_dst_alloc; /* Allocated sem_wait_dst */ + + VkSemaphore *sem_sig; + int sem_sig_alloc; /* Allocated sem_sig */ + int sem_sig_cnt; + + uint64_t *sem_sig_val; + int sem_sig_val_alloc; + + uint64_t **sem_sig_val_dst; + int sem_sig_val_dst_alloc; +} FFVkExecContext; + +typedef struct FFVulkanContext { + const AVClass *class; /* Filters and encoders use this */ + + FFVulkanFunctions vkfn; + FFVulkanExtensions extensions; + VkPhysicalDeviceProperties props; + VkPhysicalDeviceMemoryProperties mprops; + + AVBufferRef *device_ref; + AVHWDeviceContext *device; + AVVulkanDeviceContext *hwctx; + + AVBufferRef *frames_ref; + AVHWFramesContext *frames; + AVVulkanFramesContext *hwfc; + + FFVkSPIRVCompiler *spirv_compiler; + + /* Properties */ + int output_width; + int output_height; + enum AVPixelFormat output_format; + enum AVPixelFormat input_format; + + /* Samplers */ + FFVkSampler **samplers; + int samplers_num; + + /* Exec contexts */ + FFVkExecContext **exec_ctx; + int exec_ctx_num; + + /* Pipelines (each can have 1 shader of each type) */ + FFVulkanPipeline **pipelines; + int pipelines_num; + + void *scratch; /* Scratch memory used only in functions */ + unsigned int scratch_size; +} FFVulkanContext; + +/* Identity mapping - r = r, b = b, g = g, a = a */ +extern const VkComponentMapping ff_comp_identity_map; + +/** + * Converts Vulkan return values to strings + */ +const char *ff_vk_ret2str(VkResult res); + +/** + * Returns 1 if the image is any sort of supported RGB + */ +int ff_vk_mt_is_np_rgb(enum AVPixelFormat pix_fmt); + +/** + * Gets the glsl format string for a pixel format + */ +const char *ff_vk_shader_rep_fmt(enum AVPixelFormat pixfmt); + +/** + * Initialize a queue family with a specific number of queues. + * If nb_queues == 0, use however many queues the queue family has. + */ +void ff_vk_qf_init(FFVulkanContext *s, FFVkQueueFamilyCtx *qf, + VkQueueFlagBits dev_family, int nb_queues); + +/** + * Rotate through the queues in a queue family. + */ +void ff_vk_qf_rotate(FFVkQueueFamilyCtx *qf); + +/** + * Create a Vulkan sampler, will be auto-freed in ff_vk_filter_uninit() + */ +FFVkSampler *ff_vk_init_sampler(FFVulkanContext *s, int unnorm_coords, + VkFilter filt); + +/** + * Create an imageview. + * Guaranteed to remain alive until the queue submission has finished executing, + * and will be destroyed after that. + */ +int ff_vk_create_imageview(FFVulkanContext *s, FFVkExecContext *e, + VkImageView *v, VkImage img, VkFormat fmt, + const VkComponentMapping map); + +/** + * Define a push constant for a given stage into a pipeline. + * Must be called before the pipeline layout has been initialized. + */ +int ff_vk_add_push_constant(FFVulkanPipeline *pl, int offset, int size, + VkShaderStageFlagBits stage); + +/** + * Inits a pipeline. Everything in it will be auto-freed when calling + * ff_vk_filter_uninit(). + */ +FFVulkanPipeline *ff_vk_create_pipeline(FFVulkanContext *s, FFVkQueueFamilyCtx *qf); + +/** + * Inits a shader for a specific pipeline. Will be auto-freed on uninit. + */ +FFVkSPIRVShader *ff_vk_init_shader(FFVulkanPipeline *pl, const char *name, + VkShaderStageFlags stage); + +/** + * Writes the workgroup size for a shader. + */ +void ff_vk_set_compute_shader_sizes(FFVkSPIRVShader *shd, int local_size[3]); + +/** + * Adds a descriptor set to the shader and registers them in the pipeline. + */ +int ff_vk_add_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + FFVkSPIRVShader *shd, FFVulkanDescriptorSetBinding *desc, + int num, int only_print_to_shader); + +/** + * Compiles the shader, entrypoint must be set to "main". + */ +int ff_vk_compile_shader(FFVulkanContext *s, FFVkSPIRVShader *shd, + const char *entrypoint); + +/** + * Pretty print shader, mainly used by shader compilers. + */ +void ff_vk_print_shader(void *ctx, FFVkSPIRVShader *shd, int prio); + +/** + * Initializes the pipeline layout after all shaders and descriptor sets have + * been finished. + */ +int ff_vk_init_pipeline_layout(FFVulkanContext *s, FFVulkanPipeline *pl); + +/** + * Initializes a compute pipeline. Will pick the first shader with the + * COMPUTE flag set. + */ +int ff_vk_init_compute_pipeline(FFVulkanContext *s, FFVulkanPipeline *pl); + +/** + * Updates a descriptor set via the updaters defined. + * Can be called immediately after pipeline creation, but must be called + * at least once before queue submission. + */ +void ff_vk_update_descriptor_set(FFVulkanContext *s, FFVulkanPipeline *pl, + int set_id); + +/** + * Init an execution context for command recording and queue submission. + * WIll be auto-freed on uninit. + */ +int ff_vk_create_exec_ctx(FFVulkanContext *s, FFVkExecContext **ctx, + FFVkQueueFamilyCtx *qf); + +/** + * Begin recording to the command buffer. Previous execution must have been + * completed, which ff_vk_submit_exec_queue() will ensure. + */ +int ff_vk_start_exec_recording(FFVulkanContext *s, FFVkExecContext *e); + +/** + * Add a command to bind the completed pipeline and its descriptor sets. + * Must be called after ff_vk_start_exec_recording() and before submission. + */ +void ff_vk_bind_pipeline_exec(FFVulkanContext *s, FFVkExecContext *e, + FFVulkanPipeline *pl); + +/** + * Updates push constants. + * Must be called after binding a pipeline if any push constants were defined. + */ +void ff_vk_update_push_exec(FFVulkanContext *s, FFVkExecContext *e, + VkShaderStageFlagBits stage, int offset, + size_t size, void *src); + +/** + * Gets the command buffer to use for this submission from the exe context. + */ +VkCommandBuffer ff_vk_get_exec_buf(FFVkExecContext *e); + +/** + * Adds a generic AVBufferRef as a queue depenency. + */ +int ff_vk_add_dep_exec_ctx(FFVulkanContext *s, FFVkExecContext *e, + AVBufferRef **deps, int nb_deps); + +/** + * Discards all queue dependencies + */ +void ff_vk_discard_exec_deps(FFVkExecContext *e); + +/** + * Adds a frame as a queue dependency. This also manages semaphore signalling. + * Must be called before submission. + */ +int ff_vk_add_exec_dep(FFVulkanContext *s, FFVkExecContext *e, AVFrame *frame, + VkPipelineStageFlagBits in_wait_dst_flag); + +/** + * Submits a command buffer to the queue for execution. + * Will block until execution has finished in order to simplify resource + * management. + */ +int ff_vk_submit_exec_queue(FFVulkanContext *s, FFVkExecContext *e); + +/** + * Create a VkBuffer with the specified parameters. + */ +int ff_vk_create_buf(FFVulkanContext *s, FFVkBuffer *buf, size_t size, + VkBufferUsageFlags usage, VkMemoryPropertyFlagBits flags); + +/** + * Maps the buffer to userspace. Set invalidate to 1 if reading the contents + * is necessary. + */ +int ff_vk_map_buffers(FFVulkanContext *s, FFVkBuffer *buf, uint8_t *mem[], + int nb_buffers, int invalidate); + +/** + * Unmaps the buffer from userspace. Set flush to 1 to write and sync. + */ +int ff_vk_unmap_buffers(FFVulkanContext *s, FFVkBuffer *buf, int nb_buffers, + int flush); + +/** + * Frees a buffer. + */ +void ff_vk_free_buf(FFVulkanContext *s, FFVkBuffer *buf); + +/** + * Frees the main Vulkan context. + */ +void ff_vk_uninit(FFVulkanContext *s); + +#endif /* AVUTIL_VULKAN_H */ diff --git a/libavutil/vulkan_functions.h b/libavutil/vulkan_functions.h new file mode 100644 index 0000000000..96922d7286 --- /dev/null +++ b/libavutil/vulkan_functions.h @@ -0,0 +1,182 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VULKAN_FUNCTIONS_H +#define AVUTIL_VULKAN_FUNCTIONS_H + +#define VK_NO_PROTOTYPES +#define VK_ENABLE_BETA_EXTENSIONS + +#include "hwcontext.h" +#include "hwcontext_vulkan.h" + +/* An enum of bitflags for every optional extension we need */ +typedef enum FFVulkanExtensions { + FF_VK_EXT_EXTERNAL_DMABUF_MEMORY = 1ULL << 0, /* VK_EXT_external_memory_dma_buf */ + FF_VK_EXT_DRM_MODIFIER_FLAGS = 1ULL << 1, /* VK_EXT_image_drm_format_modifier */ + FF_VK_EXT_EXTERNAL_FD_MEMORY = 1ULL << 2, /* VK_KHR_external_memory_fd */ + FF_VK_EXT_EXTERNAL_FD_SEM = 1ULL << 3, /* VK_KHR_external_semaphore_fd */ + FF_VK_EXT_EXTERNAL_HOST_MEMORY = 1ULL << 4, /* VK_EXT_external_memory_host */ + FF_VK_EXT_DEBUG_UTILS = 1ULL << 5, /* VK_EXT_debug_utils */ +#ifdef _WIN32 + FF_VK_EXT_EXTERNAL_WIN32_MEMORY = 1ULL << 6, /* VK_KHR_external_memory_win32 */ + FF_VK_EXT_EXTERNAL_WIN32_SEM = 1ULL << 7, /* VK_KHR_external_semaphore_win32 */ +#endif + + FF_VK_EXT_NO_FLAG = 1ULL << 63, +} FFVulkanExtensions; + +/* Macro containing every function that we utilize in our codebase */ +#define FN_LIST(MACRO) \ + /* Instance */ \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceExtensionProperties) \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, EnumerateInstanceLayerProperties) \ + MACRO(0, 0, FF_VK_EXT_NO_FLAG, CreateInstance) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyInstance) \ + \ + /* Debug */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDebugUtilsMessengerEXT) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDebugUtilsMessengerEXT) \ + \ + /* Device */ \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetDeviceProcAddr) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, CreateDevice) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFeatures2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DeviceWaitIdle) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, DestroyDevice) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumeratePhysicalDevices) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, EnumerateDeviceExtensionProperties) \ + \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceMemoryProperties) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceImageFormatProperties2) \ + MACRO(1, 0, FF_VK_EXT_NO_FLAG, GetPhysicalDeviceQueueFamilyProperties) \ + \ + /* Command pool */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateCommandPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyCommandPool) \ + \ + /* Command buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BeginCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, EndCommandBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeCommandBuffers) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdDispatch) \ + \ + /* Queue */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetDeviceQueue) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, QueueSubmit) \ + \ + /* Fences */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateFence) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitForFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, ResetFences) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyFence) \ + \ + /* Semaphores */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_SEM, GetSemaphoreFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSemaphore) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, WaitSemaphores) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySemaphore) \ + \ + /* Memory */ \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_FD_MEMORY, GetMemoryFdKHR) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetMemoryFdPropertiesKHR) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_HOST_MEMORY, GetMemoryHostPointerPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, MapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FlushMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, InvalidateMappedMemoryRanges) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UnmapMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, FreeMemory) \ + \ + /* Commands */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPushConstants) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdBindPipeline) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdPipelineBarrier) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyBufferToImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CmdCopyImageToBuffer) \ + \ + /* Buffer */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetBufferMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateBuffer) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindBufferMemory) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyBuffer) \ + \ + /* Image */ \ + MACRO(1, 1, FF_VK_EXT_DRM_MODIFIER_FLAGS, GetImageDrmFormatModifierPropertiesEXT) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageMemoryRequirements2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImage) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, BindImageMemory2) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, GetImageSubresourceLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImage) \ + \ + /* ImageView */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateImageView) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyImageView) \ + \ + /* DescriptorSet */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorSetLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, AllocateDescriptorSets) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorPool) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorSetLayout) \ + \ + /* DescriptorUpdateTemplate */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, UpdateDescriptorSetWithTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateDescriptorUpdateTemplate) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyDescriptorUpdateTemplate) \ + \ + /* Pipeline */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreatePipelineLayout) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipelineLayout) \ + \ + /* PipelineLayout */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateComputePipelines) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyPipeline) \ + \ + /* Sampler */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateSampler) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroySampler) \ + \ + /* Shaders */ \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, CreateShaderModule) \ + MACRO(1, 1, FF_VK_EXT_NO_FLAG, DestroyShaderModule) + +/* Macro containing every win32 specific function that we utilize in our codebase */ +#define FN_LIST_WIN32(MACRO) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_SEM, GetSemaphoreWin32HandleKHR) \ + MACRO(1, 1, FF_VK_EXT_EXTERNAL_WIN32_MEMORY, GetMemoryWin32HandleKHR) + +/* Macro to turn a function name into a definition */ +#define PFN_DEF(req_inst, req_dev, ext_flag, name) \ + PFN_vk##name name; + +/* Structure with the definition of all listed functions */ +typedef struct FFVulkanFunctions { + FN_LIST(PFN_DEF) +#ifdef _WIN32 + FN_LIST_WIN32(PFN_DEF) +#endif +} FFVulkanFunctions; + +#endif /* AVUTIL_VULKAN_FUNCTIONS_H */ diff --git a/libavutil/vulkan_glslang.c b/libavutil/vulkan_glslang.c new file mode 100644 index 0000000000..e7785f6d40 --- /dev/null +++ b/libavutil/vulkan_glslang.c @@ -0,0 +1,280 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "mem.h" +#include "avassert.h" + +static pthread_mutex_t glslc_mutex = PTHREAD_MUTEX_INITIALIZER; +static int glslc_refcount = 0; + +static const glslang_resource_t glslc_resource_limits = { + .max_lights = 32, + .max_clip_planes = 6, + .max_texture_units = 32, + .max_texture_coords = 32, + .max_vertex_attribs = 64, + .max_vertex_uniform_components = 4096, + .max_varying_floats = 64, + .max_vertex_texture_image_units = 32, + .max_combined_texture_image_units = 80, + .max_texture_image_units = 32, + .max_fragment_uniform_components = 4096, + .max_draw_buffers = 32, + .max_vertex_uniform_vectors = 128, + .max_varying_vectors = 8, + .max_fragment_uniform_vectors = 16, + .max_vertex_output_vectors = 16, + .max_fragment_input_vectors = 15, + .min_program_texel_offset = -8, + .max_program_texel_offset = 7, + .max_clip_distances = 8, + .max_compute_work_group_count_x = 65535, + .max_compute_work_group_count_y = 65535, + .max_compute_work_group_count_z = 65535, + .max_compute_work_group_size_x = 1024, + .max_compute_work_group_size_y = 1024, + .max_compute_work_group_size_z = 64, + .max_compute_uniform_components = 1024, + .max_compute_texture_image_units = 16, + .max_compute_image_uniforms = 8, + .max_compute_atomic_counters = 8, + .max_compute_atomic_counter_buffers = 1, + .max_varying_components = 60, + .max_vertex_output_components = 64, + .max_geometry_input_components = 64, + .max_geometry_output_components = 128, + .max_fragment_input_components = 128, + .max_image_units = 8, + .max_combined_image_units_and_fragment_outputs = 8, + .max_combined_shader_output_resources = 8, + .max_image_samples = 0, + .max_vertex_image_uniforms = 0, + .max_tess_control_image_uniforms = 0, + .max_tess_evaluation_image_uniforms = 0, + .max_geometry_image_uniforms = 0, + .max_fragment_image_uniforms = 8, + .max_combined_image_uniforms = 8, + .max_geometry_texture_image_units = 16, + .max_geometry_output_vertices = 256, + .max_geometry_total_output_components = 1024, + .max_geometry_uniform_components = 1024, + .max_geometry_varying_components = 64, + .max_tess_control_input_components = 128, + .max_tess_control_output_components = 128, + .max_tess_control_texture_image_units = 16, + .max_tess_control_uniform_components = 1024, + .max_tess_control_total_output_components = 4096, + .max_tess_evaluation_input_components = 128, + .max_tess_evaluation_output_components = 128, + .max_tess_evaluation_texture_image_units = 16, + .max_tess_evaluation_uniform_components = 1024, + .max_tess_patch_components = 120, + .max_patch_vertices = 32, + .max_tess_gen_level = 64, + .max_viewports = 16, + .max_vertex_atomic_counters = 0, + .max_tess_control_atomic_counters = 0, + .max_tess_evaluation_atomic_counters = 0, + .max_geometry_atomic_counters = 0, + .max_fragment_atomic_counters = 8, + .max_combined_atomic_counters = 8, + .max_atomic_counter_bindings = 1, + .max_vertex_atomic_counter_buffers = 0, + .max_tess_control_atomic_counter_buffers = 0, + .max_tess_evaluation_atomic_counter_buffers = 0, + .max_geometry_atomic_counter_buffers = 0, + .max_fragment_atomic_counter_buffers = 1, + .max_combined_atomic_counter_buffers = 1, + .max_atomic_counter_buffer_size = 16384, + .max_transform_feedback_buffers = 4, + .max_transform_feedback_interleaved_components = 64, + .max_cull_distances = 8, + .max_combined_clip_and_cull_distances = 8, + .max_samples = 4, + .max_mesh_output_vertices_nv = 256, + .max_mesh_output_primitives_nv = 512, + .max_mesh_work_group_size_x_nv = 32, + .max_mesh_work_group_size_y_nv = 1, + .max_mesh_work_group_size_z_nv = 1, + .max_task_work_group_size_x_nv = 32, + .max_task_work_group_size_y_nv = 1, + .max_task_work_group_size_z_nv = 1, + .max_mesh_view_count_nv = 4, + .maxDualSourceDrawBuffersEXT = 1, + + .limits = { + .non_inductive_for_loops = 1, + .while_loops = 1, + .do_while_loops = 1, + .general_uniform_indexing = 1, + .general_attribute_matrix_vector_indexing = 1, + .general_varying_indexing = 1, + .general_sampler_indexing = 1, + .general_variable_indexing = 1, + .general_constant_matrix_vector_indexing = 1, + } +}; + +static int glslc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, + FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, + void **opaque) +{ + const char *messages; + glslang_shader_t *glslc_shader; + glslang_program_t *glslc_program; + + static const glslang_stage_t glslc_stage[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = GLSLANG_STAGE_VERTEX, + [VK_SHADER_STAGE_FRAGMENT_BIT] = GLSLANG_STAGE_FRAGMENT, + [VK_SHADER_STAGE_COMPUTE_BIT] = GLSLANG_STAGE_COMPUTE, + }; + + const glslang_input_t glslc_input = { + .language = GLSLANG_SOURCE_GLSL, + .stage = glslc_stage[shd->shader.stage], + .client = GLSLANG_CLIENT_VULKAN, + /* GLSLANG_TARGET_VULKAN_1_2 before 11.6 resulted in targeting 1.0 */ +#if (((GLSLANG_VERSION_MAJOR) > 11) || ((GLSLANG_VERSION_MAJOR) == 11 && \ + (((GLSLANG_VERSION_MINOR) > 6) || ((GLSLANG_VERSION_MINOR) == 6 && \ + ((GLSLANG_VERSION_PATCH) > 0))))) + .client_version = GLSLANG_TARGET_VULKAN_1_2, + .target_language_version = GLSLANG_TARGET_SPV_1_5, +#else + .client_version = GLSLANG_TARGET_VULKAN_1_1, + .target_language_version = GLSLANG_TARGET_SPV_1_3, +#endif + .target_language = GLSLANG_TARGET_SPV, + .code = shd->src.str, + .default_version = 460, + .default_profile = GLSLANG_NO_PROFILE, + .force_default_version_and_profile = false, + .forward_compatible = false, + .messages = GLSLANG_MSG_DEFAULT_BIT, + .resource = &glslc_resource_limits, + }; + + av_assert0(glslc_refcount); + + if (!(glslc_shader = glslang_shader_create(&glslc_input))) + return AVERROR(ENOMEM); + + if (!glslang_shader_preprocess(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to preprocess shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!glslang_shader_parse(glslc_shader, &glslc_input)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to parse shader: %s (%s)!\n", + glslang_shader_get_info_log(glslc_shader), + glslang_shader_get_info_debug_log(glslc_shader)); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + if (!(glslc_program = glslang_program_create())) { + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_add_shader(glslc_program, glslc_shader); + + if (!glslang_program_link(glslc_program, GLSLANG_MSG_SPV_RULES_BIT | + GLSLANG_MSG_VULKAN_RULES_BIT)) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_ERROR, "Unable to link shader: %s (%s)!\n", + glslang_program_get_info_log(glslc_program), + glslang_program_get_info_debug_log(glslc_program)); + glslang_program_delete(glslc_program); + glslang_shader_delete(glslc_shader); + return AVERROR(EINVAL); + } + + glslang_program_SPIRV_generate(glslc_program, glslc_input.stage); + + messages = glslang_program_SPIRV_get_messages(glslc_program); + if (messages) { + ff_vk_print_shader(avctx, shd, AV_LOG_WARNING); + av_log(avctx, AV_LOG_WARNING, "%s\n", messages); + } else { + ff_vk_print_shader(avctx, shd, AV_LOG_VERBOSE); + } + + glslang_shader_delete(glslc_shader); + + *size = glslang_program_SPIRV_get_size(glslc_program) * sizeof(unsigned int); + *data = (void *)glslang_program_SPIRV_get_ptr(glslc_program); + *opaque = glslc_program; + + return 0; +} + +static void glslc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque) +{ + if (!opaque || !*opaque) + return; + + av_assert0(glslc_refcount); + glslang_program_delete(*opaque); + *opaque = NULL; +} + +static void glslc_uninit(FFVkSPIRVCompiler **ctx) +{ + if (!ctx || !*ctx) + return; + + pthread_mutex_lock(&glslc_mutex); + if (glslc_refcount && (--glslc_refcount == 0)) + glslang_finalize_process(); + pthread_mutex_unlock(&glslc_mutex); + + av_freep(ctx); +} + +static FFVkSPIRVCompiler *ff_vk_glslang_init(void) +{ + FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); + if (!ret) + return NULL; + + ret->compile_shader = glslc_shader_compile; + ret->free_shader = glslc_shader_free; + ret->uninit = glslc_uninit; + + pthread_mutex_lock(&glslc_mutex); + if (!glslc_refcount++) { + if (!glslang_initialize_process()) { + av_freep(&ret); + glslc_refcount--; + } + } + pthread_mutex_unlock(&glslc_mutex); + + return ret; +} diff --git a/libavutil/vulkan_loader.h b/libavutil/vulkan_loader.h new file mode 100644 index 0000000000..3f1ee6aa46 --- /dev/null +++ b/libavutil/vulkan_loader.h @@ -0,0 +1,135 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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_VULKAN_LOADER_H +#define AVUTIL_VULKAN_LOADER_H + +#include "vulkan_functions.h" + +/* Macro to turn a function name into a loader struct */ +#define PFN_LOAD_INFO(req_inst, req_dev, ext_flag, name) \ + { \ + req_inst, \ + req_dev, \ + offsetof(FFVulkanFunctions, name), \ + ext_flag, \ + { "vk"#name, "vk"#name"EXT", "vk"#name"KHR" } \ + }, + +static inline uint64_t ff_vk_extensions_to_mask(const char * const *extensions, + int nb_extensions) +{ + static const struct ExtensionMap { + const char *name; + FFVulkanExtensions flag; + } extension_map[] = { + { VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_DMABUF_MEMORY }, + { VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME, FF_VK_EXT_DRM_MODIFIER_FLAGS }, + { VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_FD_SEM }, + { VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_HOST_MEMORY }, + { VK_EXT_DEBUG_UTILS_EXTENSION_NAME, FF_VK_EXT_DEBUG_UTILS }, +#ifdef _WIN32 + { VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_MEMORY }, + { VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME, FF_VK_EXT_EXTERNAL_WIN32_SEM }, +#endif + }; + + FFVulkanExtensions mask = 0x0; + + for (int i = 0; i < nb_extensions; i++) { + for (int j = 0; j < FF_ARRAY_ELEMS(extension_map); j++) { + if (!strcmp(extensions[i], extension_map[j].name)) { + mask |= extension_map[j].flag; + continue; + } + } + } + + return mask; +} + +/** + * Function loader. + * Vulkan function from scratch loading happens in 3 stages - the first one + * is before any initialization has happened, and you have neither an instance + * structure nor a device structure. At this stage, you can only get the bare + * minimals to initialize an instance. + * The second stage is when you have an instance. At this stage, you can + * initialize a VkDevice, and have an idea of what extensions each device + * supports. + * Finally, in the third stage, you can proceed and load all core functions, + * plus you can be sure that any extensions you've enabled during device + * initialization will be available. + */ +static inline int ff_vk_load_functions(AVHWDeviceContext *ctx, + FFVulkanFunctions *vk, + uint64_t extensions_mask, + int has_inst, int has_dev) +{ + AVVulkanDeviceContext *hwctx = ctx->hwctx; + + static const struct FunctionLoadInfo { + int req_inst; + int req_dev; + size_t struct_offset; + FFVulkanExtensions ext_flag; + const char *names[3]; + } vk_load_info[] = { + FN_LIST(PFN_LOAD_INFO) +#ifdef _WIN32 + FN_LIST_WIN32(PFN_LOAD_INFO) +#endif + }; + + for (int i = 0; i < FF_ARRAY_ELEMS(vk_load_info); i++) { + const struct FunctionLoadInfo *load = &vk_load_info[i]; + PFN_vkVoidFunction fn; + + if (load->req_dev && !has_dev) + continue; + if (load->req_inst && !has_inst) + continue; + + for (int j = 0; j < FF_ARRAY_ELEMS(load->names); j++) { + const char *name = load->names[j]; + + if (load->req_dev) + fn = vk->GetDeviceProcAddr(hwctx->act_dev, name); + else if (load->req_inst) + fn = hwctx->get_proc_addr(hwctx->inst, name); + else + fn = hwctx->get_proc_addr(NULL, name); + + if (fn) + break; + } + + if (!fn && ((extensions_mask &~ FF_VK_EXT_NO_FLAG) & load->ext_flag)) { + av_log(ctx, AV_LOG_ERROR, "Loader error, function \"%s\" indicated " + "as supported, but got NULL function pointer!\n", load->names[0]); + return AVERROR_EXTERNAL; + } + + *(PFN_vkVoidFunction *)((uint8_t *)vk + load->struct_offset) = fn; + } + + return 0; +} + +#endif /* AVUTIL_VULKAN_LOADER_H */ diff --git a/libavutil/vulkan_shaderc.c b/libavutil/vulkan_shaderc.c new file mode 100644 index 0000000000..bd40edf187 --- /dev/null +++ b/libavutil/vulkan_shaderc.c @@ -0,0 +1,122 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General 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 "mem.h" + +static int shdc_shader_compile(FFVkSPIRVCompiler *ctx, void *avctx, + FFVkSPIRVShader *shd, uint8_t **data, + size_t *size, const char *entrypoint, + void **opaque) +{ + int loglevel, err, warn, ret; + const char *status, *message; + shaderc_compilation_result_t res; + static const char *shdc_result[] = { + [shaderc_compilation_status_success] = "success", + [shaderc_compilation_status_invalid_stage] = "invalid stage", + [shaderc_compilation_status_compilation_error] = "error", + [shaderc_compilation_status_internal_error] = "internal error", + [shaderc_compilation_status_null_result_object] = "no result", + [shaderc_compilation_status_invalid_assembly] = "invalid assembly", + }; + static const shaderc_shader_kind shdc_kind[] = { + [VK_SHADER_STAGE_VERTEX_BIT] = shaderc_glsl_vertex_shader, + [VK_SHADER_STAGE_FRAGMENT_BIT] = shaderc_glsl_fragment_shader, + [VK_SHADER_STAGE_COMPUTE_BIT] = shaderc_glsl_compute_shader, + }; + + shaderc_compile_options_t opts = shaderc_compile_options_initialize(); + if (!opts) + return AVERROR(ENOMEM); + + shaderc_compile_options_set_target_env(opts, shaderc_target_env_vulkan, + shaderc_env_version_vulkan_1_2); + shaderc_compile_options_set_target_spirv(opts, shaderc_spirv_version_1_5); + shaderc_compile_options_set_optimization_level(opts, + shaderc_optimization_level_performance); + + res = shaderc_compile_into_spv((shaderc_compiler_t)ctx->priv, + shd->src.str, strlen(shd->src.str), + shdc_kind[shd->shader.stage], + shd->name, entrypoint, opts); + shaderc_compile_options_release(opts); + + ret = shaderc_result_get_compilation_status(res); + err = shaderc_result_get_num_errors(res); + warn = shaderc_result_get_num_warnings(res); + message = shaderc_result_get_error_message(res); + + loglevel = err ? AV_LOG_ERROR : warn ? AV_LOG_WARNING : AV_LOG_VERBOSE; + + ff_vk_print_shader(avctx, shd, loglevel); + if (message && (err || warn)) + av_log(avctx, loglevel, "%s\n", message); + status = ret < FF_ARRAY_ELEMS(shdc_result) ? shdc_result[ret] : "unknown"; + av_log(avctx, loglevel, "shaderc compile status '%s' (%d errors, %d warnings)\n", + status, err, warn); + + if (err > 0) + return AVERROR(EINVAL); + + *data = (uint8_t *)shaderc_result_get_bytes(res); + *size = shaderc_result_get_length(res); + *opaque = res; + + return 0; +} + +static void shdc_shader_free(FFVkSPIRVCompiler *ctx, void **opaque) +{ + if (!opaque || !*opaque) + return; + + shaderc_result_release((shaderc_compilation_result_t)*opaque); + *opaque = NULL; +} + +static void shdc_uninit(FFVkSPIRVCompiler **ctx) +{ + FFVkSPIRVCompiler *s; + + if (!ctx || !*ctx) + return; + + s = *ctx; + + shaderc_compiler_release((shaderc_compiler_t)s->priv); + av_freep(ctx); +} + +static FFVkSPIRVCompiler *ff_vk_shaderc_init(void) +{ + FFVkSPIRVCompiler *ret = av_mallocz(sizeof(*ret)); + if (!ret) + return NULL; + + ret->compile_shader = shdc_shader_compile; + ret->free_shader = shdc_shader_free; + ret->uninit = shdc_uninit; + + ret->priv = (void *)shaderc_compiler_initialize(); + if (!ret->priv) + av_freep(&ret); + + return ret; +} diff --git a/libavutil/x86/cpu.c b/libavutil/x86/cpu.c index bcd41a50a2..7b13fcae91 100644 --- a/libavutil/x86/cpu.c +++ b/libavutil/x86/cpu.c @@ -196,6 +196,10 @@ int ff_get_cpu_flags_x86(void) used unless explicitly disabled by checking AV_CPU_FLAG_AVXSLOW. */ if ((family == 0x15 || family == 0x16) && (rval & AV_CPU_FLAG_AVX)) rval |= AV_CPU_FLAG_AVXSLOW; + + /* Zen 3 and earlier have slow gather */ + if ((family <= 0x19) && (rval & AV_CPU_FLAG_AVX2)) + rval |= AV_CPU_FLAG_SLOW_GATHER; } /* XOP and FMA4 use the AVX instruction coding scheme, so they can't be @@ -235,6 +239,10 @@ int ff_get_cpu_flags_x86(void) if ((rval & AV_CPU_FLAG_SSSE3) && !(rval & AV_CPU_FLAG_SSE4) && family == 6 && model < 23) rval |= AV_CPU_FLAG_SSSE3SLOW; + + /* Haswell has slow gather */ + if ((rval & AV_CPU_FLAG_AVX2) && family == 6 && model < 70) + rval |= AV_CPU_FLAG_SLOW_GATHER; } #endif /* cpuid */ diff --git a/libavutil/x86/intmath.h b/libavutil/x86/intmath.h index 40743fd13e..8a6b5ae261 100644 --- a/libavutil/x86/intmath.h +++ b/libavutil/x86/intmath.h @@ -110,8 +110,8 @@ static av_always_inline av_const double av_clipd_sse2(double a, double amin, dou #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - __asm__ ("minsd %2, %0 \n\t" - "maxsd %1, %0 \n\t" + __asm__ ("maxsd %1, %0 \n\t" + "minsd %2, %0 \n\t" : "+&x"(a) : "xm"(amin), "xm"(amax)); return a; } @@ -126,14 +126,44 @@ static av_always_inline av_const float av_clipf_sse(float a, float amin, float a #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 if (amin > amax) abort(); #endif - __asm__ ("minss %2, %0 \n\t" - "maxss %1, %0 \n\t" + __asm__ ("maxss %1, %0 \n\t" + "minss %2, %0 \n\t" : "+&x"(a) : "xm"(amin), "xm"(amax)); return a; } #endif /* __SSE__ */ +#if defined(__AVX__) && !defined(__INTEL_COMPILER) + +#undef av_clipd +#define av_clipd av_clipd_avx +static av_always_inline av_const double av_clipd_avx(double a, double amin, double amax) +{ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + __asm__ ("vmaxsd %1, %0, %0 \n\t" + "vminsd %2, %0, %0 \n\t" + : "+&x"(a) : "xm"(amin), "xm"(amax)); + return a; +} + +#undef av_clipf +#define av_clipf av_clipf_avx +static av_always_inline av_const float av_clipf_avx(float a, float amin, float amax) +{ +#if defined(ASSERT_LEVEL) && ASSERT_LEVEL >= 2 + if (amin > amax) abort(); +#endif + __asm__ ("vmaxss %1, %0, %0 \n\t" + "vminss %2, %0, %0 \n\t" + : "+&x"(a) : "xm"(amin), "xm"(amax)); + return a; +} + +#endif /* __AVX__ */ + #endif /* __GNUC__ */ #endif /* AVUTIL_X86_INTMATH_H */ diff --git a/libpostproc/version.h b/libpostproc/version.h index e518ccf810..e8bd6afdc8 100644 --- a/libpostproc/version.h +++ b/libpostproc/version.h @@ -29,7 +29,7 @@ #include "libavutil/version.h" #define LIBPOSTPROC_VERSION_MAJOR 56 -#define LIBPOSTPROC_VERSION_MINOR 0 +#define LIBPOSTPROC_VERSION_MINOR 4 #define LIBPOSTPROC_VERSION_MICRO 100 #define LIBPOSTPROC_VERSION_INT AV_VERSION_INT(LIBPOSTPROC_VERSION_MAJOR, \ diff --git a/libswresample/Makefile b/libswresample/Makefile index 42666e4dd2..f528427f55 100644 --- a/libswresample/Makefile +++ b/libswresample/Makefile @@ -15,7 +15,9 @@ OBJS = audioconvert.o \ swresample_frame.o \ OBJS-$(CONFIG_LIBSOXR) += soxr_resample.o -OBJS-$(CONFIG_SHARED) += log2_tab.o + +# Objects duplicated from other libraries for shared builds +SHLIBOBJS += log2_tab.o # Windows resource file SLIBOBJS-$(HAVE_GNU_WINDRES) += swresampleres.o diff --git a/libswresample/swresample.c b/libswresample/swresample.c index 22c2c33673..16734c9df9 100644 --- a/libswresample/swresample.c +++ b/libswresample/swresample.c @@ -643,14 +643,16 @@ static int swr_convert_internal(struct SwrContext *s, AudioData *out, int out_co if(s->resample_first){ if(postin != midbuf) - out_count= resample(s, midbuf, out_count, postin, in_count); + if ((out_count = resample(s, midbuf, out_count, postin, in_count)) < 0) + return out_count; if(midbuf != preout) swri_rematrix(s, preout, midbuf, out_count, preout==out); }else{ if(postin != midbuf) swri_rematrix(s, midbuf, postin, in_count, midbuf==out); if(midbuf != preout) - out_count= resample(s, preout, out_count, midbuf, in_count); + if ((out_count = resample(s, preout, out_count, midbuf, in_count)) < 0) + return out_count; } if(preout != out && out_count){ @@ -711,8 +713,10 @@ int swr_is_initialized(struct SwrContext *s) { return !!s->in_buffer.ch_count; } -int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, - const uint8_t *in_arg [SWR_CH_MAX], int in_count){ +int attribute_align_arg swr_convert(struct SwrContext *s, + uint8_t **out_arg, int out_count, + const uint8_t **in_arg, int in_count) +{ AudioData * in= &s->in; AudioData *out= &s->out; int av_unused max_output; @@ -767,7 +771,7 @@ int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_C if(ret>0 && !s->drop_output) s->outpts += ret * (int64_t)s->in_sample_rate; - av_assert2(max_output < 0 || ret < 0 || ret <= max_output); + av_assert2(max_output < 0 || ret <= max_output); return ret; }else{ diff --git a/libswresample/tests/swresample.c b/libswresample/tests/swresample.c index 53896585e2..14a8f14f3e 100644 --- a/libswresample/tests/swresample.c +++ b/libswresample/tests/swresample.c @@ -362,16 +362,12 @@ int main(int argc, char **argv){ for(ch=0; ch> RGB2YUV_SHIFT; dstV[i] = (rv*r + gv*g + bv*b + (0x10001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; @@ -1005,39 +1005,27 @@ static av_always_inline void planar_rgbf32_to_y(uint8_t *_dst, const uint8_t *_s int32_t ry = rgb2yuv[RY_IDX], gy = rgb2yuv[GY_IDX], by = rgb2yuv[BY_IDX]; for (i = 0; i < width; i++) { - int g = av_clip_uint16(lrintf(65535.0f * rdpx(src[0] + i))); - int b = av_clip_uint16(lrintf(65535.0f * rdpx(src[1] + i))); - int r = av_clip_uint16(lrintf(65535.0f * rdpx(src[2] + i))); + int g = lrintf(av_clipf(65535.0f * rdpx(src[0] + i), 0.0f, 65535.0f)); + int b = lrintf(av_clipf(65535.0f * rdpx(src[1] + i), 0.0f, 65535.0f)); + int r = lrintf(av_clipf(65535.0f * rdpx(src[2] + i), 0.0f, 65535.0f)); dst[i] = (ry*r + gy*g + by*b + (0x2001 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT; } } -#undef rdpx - static av_always_inline void grayf32ToY16_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, - const uint8_t *unused2, int width, uint32_t *unused) + const uint8_t *unused2, int width, int is_be, uint32_t *unused) { int i; const float *src = (const float *)_src; uint16_t *dst = (uint16_t *)_dst; for (i = 0; i < width; ++i){ - dst[i] = av_clip_uint16(lrintf(65535.0f * src[i])); + dst[i] = lrintf(av_clipf(65535.0f * rdpx(src + i), 0.0f, 65535.0f)); } } -static av_always_inline void grayf32ToY16_bswap_c(uint8_t *_dst, const uint8_t *_src, const uint8_t *unused1, - const uint8_t *unused2, int width, uint32_t *unused) -{ - int i; - const uint32_t *src = (const uint32_t *)_src; - uint16_t *dst = (uint16_t *)_dst; - - for (i = 0; i < width; ++i){ - dst[i] = av_clip_uint16(lrintf(65535.0f * av_int2float(av_bswap32(src[i])))); - } -} +#undef rdpx #define rgb9plus_planar_funcs_endian(nbits, endian_name, endian) \ static void planar_rgb##nbits##endian_name##_to_y(uint8_t *dst, const uint8_t *src[4], \ @@ -1092,6 +1080,12 @@ static void planar_rgbf32##endian_name##_to_a(uint8_t *dst, const uint8_t *src[4 int w, int32_t *rgb2yuv) \ { \ planar_rgbf32_to_a(dst, src, w, endian, rgb2yuv); \ +} \ +static void grayf32##endian_name##ToY16_c(uint8_t *dst, const uint8_t *src, \ + const uint8_t *unused1, const uint8_t *unused2, \ + int width, uint32_t *unused) \ +{ \ + grayf32ToY16_c(dst, src, unused1, unused2, width, endian, unused); \ } rgbf32_planar_funcs_endian(le, 0) @@ -1244,15 +1238,23 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->chrToYV12 = read_ayuv64le_UV_c; break; case AV_PIX_FMT_P010LE: + case AV_PIX_FMT_P210LE: + case AV_PIX_FMT_P410LE: c->chrToYV12 = p010LEToUV_c; break; case AV_PIX_FMT_P010BE: + case AV_PIX_FMT_P210BE: + case AV_PIX_FMT_P410BE: c->chrToYV12 = p010BEToUV_c; break; case AV_PIX_FMT_P016LE: + case AV_PIX_FMT_P216LE: + case AV_PIX_FMT_P416LE: c->chrToYV12 = p016LEToUV_c; break; case AV_PIX_FMT_P016BE: + case AV_PIX_FMT_P216BE: + case AV_PIX_FMT_P416BE: c->chrToYV12 = p016BEToUV_c; break; case AV_PIX_FMT_Y210LE: @@ -1525,6 +1527,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GRAY16LE: case AV_PIX_FMT_P016LE: + case AV_PIX_FMT_P216LE: + case AV_PIX_FMT_P416LE: c->lumToYV12 = bswap16Y_c; break; case AV_PIX_FMT_YUVA420P9LE: @@ -1567,6 +1571,8 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) case AV_PIX_FMT_GRAY16BE: case AV_PIX_FMT_P016BE: + case AV_PIX_FMT_P216BE: + case AV_PIX_FMT_P416BE: c->lumToYV12 = bswap16Y_c; break; case AV_PIX_FMT_YUVA420P9BE: @@ -1693,24 +1699,20 @@ av_cold void ff_sws_init_input_funcs(SwsContext *c) c->lumToYV12 = bgr64LEToY_c; break; case AV_PIX_FMT_P010LE: + case AV_PIX_FMT_P210LE: + case AV_PIX_FMT_P410LE: c->lumToYV12 = p010LEToY_c; break; case AV_PIX_FMT_P010BE: + case AV_PIX_FMT_P210BE: + case AV_PIX_FMT_P410BE: c->lumToYV12 = p010BEToY_c; break; case AV_PIX_FMT_GRAYF32LE: -#if HAVE_BIGENDIAN - c->lumToYV12 = grayf32ToY16_bswap_c; -#else - c->lumToYV12 = grayf32ToY16_c; -#endif + c->lumToYV12 = grayf32leToY16_c; break; case AV_PIX_FMT_GRAYF32BE: -#if HAVE_BIGENDIAN - c->lumToYV12 = grayf32ToY16_c; -#else - c->lumToYV12 = grayf32ToY16_bswap_c; -#endif + c->lumToYV12 = grayf32beToY16_c; break; case AV_PIX_FMT_Y210LE: c->lumToYV12 = y210le_Y_c; diff --git a/libswscale/output.c b/libswscale/output.c index 58b10f85a5..773f3ce059 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -180,17 +180,18 @@ yuv2planeX_16_c_template(const int16_t *filter, int filterSize, } } -static void yuv2p016cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, +static av_always_inline void +yuv2nv12cX_16_c_template(int big_endian, const uint8_t *chrDither, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, const int16_t **chrVSrc, - uint8_t *dest8, int chrDstW) + uint8_t *dest8, int chrDstW, int output_bits) { uint16_t *dest = (uint16_t*)dest8; const int32_t **uSrc = (const int32_t **)chrUSrc; const int32_t **vSrc = (const int32_t **)chrVSrc; int shift = 15; - int big_endian = dstFormat == AV_PIX_FMT_P016BE; int i, j; + av_assert0(output_bits == 16); for (i = 0; i < chrDstW; i++) { int u = 1 << (shift - 1); @@ -367,6 +368,7 @@ static void yuv2planeX_ ## bits ## BE_LE ## _c(const int16_t *filter, int filter filterSize, (const typeX_t **) src, \ (uint16_t *) dest, dstW, is_be, bits); \ } + yuv2NBPS( 9, BE, 1, 10, int16_t) yuv2NBPS( 9, LE, 0, 10, int16_t) yuv2NBPS(10, BE, 1, 10, int16_t) @@ -378,6 +380,23 @@ yuv2NBPS(14, LE, 0, 10, int16_t) yuv2NBPS(16, BE, 1, 16, int32_t) yuv2NBPS(16, LE, 0, 16, int32_t) + +static void yuv2nv12cX_16LE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2nv12cX_16_c_template(0, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW, 16); +} + +static void yuv2nv12cX_16BE_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, + const int16_t *chrFilter, int chrFilterSize, + const int16_t **chrUSrc, const int16_t **chrVSrc, + uint8_t *dest8, int chrDstW) +{ + yuv2nv12cX_16_c_template(1, chrDither, chrFilter, chrFilterSize, chrUSrc, chrVSrc, dest8, chrDstW, 16); +} + static void yuv2planeX_8_c(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset) @@ -410,8 +429,7 @@ static void yuv2nv12cX_c(enum AVPixelFormat dstFormat, const uint8_t *chrDither, { int i; - if (dstFormat == AV_PIX_FMT_NV12 || - dstFormat == AV_PIX_FMT_NV24) + if (!isSwappedChroma(dstFormat)) for (i=0; idstFormat; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); - if (dstFormat == AV_PIX_FMT_P010LE || dstFormat == AV_PIX_FMT_P010BE) { + if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) { + av_assert0(desc->comp[0].depth == 10); *yuv2plane1 = isBE(dstFormat) ? yuv2p010l1_BE_c : yuv2p010l1_LE_c; *yuv2planeX = isBE(dstFormat) ? yuv2p010lX_BE_c : yuv2p010lX_LE_c; - *yuv2nv12cX = yuv2p010cX_c; + *yuv2nv12cX = isBE(dstFormat) ? yuv2p010cX_BE_c : yuv2p010cX_LE_c; } else if (is16BPS(dstFormat)) { *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c; *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c; - if (dstFormat == AV_PIX_FMT_P016LE || dstFormat == AV_PIX_FMT_P016BE) { - *yuv2nv12cX = yuv2p016cX_c; + if (isSemiPlanarYUV(dstFormat)) { + *yuv2nv12cX = isBE(dstFormat) ? yuv2nv12cX_16BE_c : yuv2nv12cX_16LE_c; } } else if (isNBPS(dstFormat)) { if (desc->comp[0].depth == 9) { @@ -2597,8 +2631,7 @@ av_cold void ff_sws_init_output_funcs(SwsContext *c, } else { *yuv2plane1 = yuv2plane1_8_c; *yuv2planeX = yuv2planeX_8_c; - if (dstFormat == AV_PIX_FMT_NV12 || dstFormat == AV_PIX_FMT_NV21 || - dstFormat == AV_PIX_FMT_NV24 || dstFormat == AV_PIX_FMT_NV42) + if (isSemiPlanarYUV(dstFormat)) *yuv2nv12cX = yuv2nv12cX_c; } diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 75cde31f4f..feef3482d2 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -329,7 +329,7 @@ static int swscale(SwsContext *c, const uint8_t *src[], ) { SwsContext *const ctx = c->parent ? c->parent : c; int cpu_flags = av_get_cpu_flags(); - if (HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) && + if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) && !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) { av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n"); } diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 59610d0342..daa53dc01e 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -318,14 +318,22 @@ unsigned int sws_receive_slice_alignment(const struct SwsContext *c); * @param brightness 16.16 fixed point brightness correction * @param contrast 16.16 fixed point contrast correction * @param saturation 16.16 fixed point saturation correction +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else * @return -1 if not supported +#endif */ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation); /** +#if LIBSWSCALE_VERSION_MAJOR > 6 + * @return negative error code on error, non negative otherwise +#else * @return -1 if not supported +#endif */ int sws_getColorspaceDetails(struct SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 708facba67..3a78d95ba6 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -892,6 +892,44 @@ static av_always_inline int usePal(enum AVPixelFormat pix_fmt) } } +/* + * Identity formats where the data is in the high bits, and the low bits are shifted away. + */ +static av_always_inline int isDataInHighBits(enum AVPixelFormat pix_fmt) +{ + int i; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + if (desc->flags & (AV_PIX_FMT_FLAG_BITSTREAM | AV_PIX_FMT_FLAG_HWACCEL)) + return 0; + for (i = 0; i < desc->nb_components; i++) { + if (!desc->comp[i].shift) + return 0; + if ((desc->comp[i].shift + desc->comp[i].depth) & 0x7) + return 0; + } + return 1; +} + +/* + * Identity formats where the chroma planes are swapped (CrCb order). + */ +static av_always_inline int isSwappedChroma(enum AVPixelFormat pix_fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + av_assert0(desc); + if (!isYUV(pix_fmt)) + return 0; + if ((desc->flags & AV_PIX_FMT_FLAG_ALPHA) && desc->nb_components < 4) + return 0; + if (desc->nb_components < 3) + return 0; + if (!isPlanarYUV(pix_fmt) || isSemiPlanarYUV(pix_fmt)) + return desc->comp[1].offset > desc->comp[2].offset; + else + return desc->comp[1].plane > desc->comp[2].plane; +} + extern const uint64_t ff_dither4[2]; extern const uint64_t ff_dither8[2]; @@ -1105,4 +1143,6 @@ void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, //number of extra lines to process #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); #endif /* SWSCALE_SWSCALE_INTERNAL_H */ diff --git a/libswscale/tests/pixdesc_query.c b/libswscale/tests/pixdesc_query.c index f6dd8bae68..eb793877a0 100644 --- a/libswscale/tests/pixdesc_query.c +++ b/libswscale/tests/pixdesc_query.c @@ -45,6 +45,8 @@ static const struct { {"PackedRGB", isPackedRGB}, {"PlanarRGB", isPlanarRGB}, {"usePal", usePal}, + {"DataInHighBits", isDataInHighBits}, + {"SwappedChroma", isSwappedChroma}, }; static int cmp_str(const void *a, const void *b) diff --git a/libswscale/utils.c b/libswscale/utils.c index 367b0ea501..c5ea8853d5 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -268,8 +268,51 @@ static const FormatEntry format_entries[] = { [AV_PIX_FMT_Y210LE] = { 1, 0 }, [AV_PIX_FMT_X2RGB10LE] = { 1, 1 }, [AV_PIX_FMT_X2BGR10LE] = { 1, 1 }, + [AV_PIX_FMT_P210BE] = { 1, 1 }, + [AV_PIX_FMT_P210LE] = { 1, 1 }, + [AV_PIX_FMT_P410BE] = { 1, 1 }, + [AV_PIX_FMT_P410LE] = { 1, 1 }, + [AV_PIX_FMT_P216BE] = { 1, 1 }, + [AV_PIX_FMT_P216LE] = { 1, 1 }, + [AV_PIX_FMT_P416BE] = { 1, 1 }, + [AV_PIX_FMT_P416LE] = { 1, 1 }, }; +void 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 cpu_flags = av_get_cpu_flags(); + 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); + } + } + } + } + } +#endif +} + int sws_isSupportedInput(enum AVPixelFormat pix_fmt) { return (unsigned)pix_fmt < FF_ARRAY_ELEMS(format_entries) ? @@ -874,15 +917,16 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], int need_reinit = 0; if (c->nb_slice_ctx) { + int parent_ret = 0; for (int i = 0; i < c->nb_slice_ctx; i++) { int ret = sws_setColorspaceDetails(c->slice_ctx[i], inv_table, srcRange, table, dstRange, brightness, contrast, saturation); if (ret < 0) - return ret; + parent_ret = ret; } - return 0; + return parent_ret; } handle_formats(c); @@ -994,7 +1038,10 @@ int sws_setColorspaceDetails(struct SwsContext *c, const int inv_table[4], 0, 1 << 16, 1 << 16); return 0; } - return -1; + //We do not support this combination currently, we need to cascade more contexts to compensate + if (c->cascaded_context[0] && memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4)) + return -1; //AVERROR_PATCHWELCOME; + return 0; } if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) { @@ -1789,6 +1836,7 @@ 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 ((ret = initFilter(&c->hChrFilter, &c->hChrFilterPos, &c->hChrFilterSize, c->chrXInc, c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, @@ -1798,6 +1846,7 @@ 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); } } // initialize horizontal stuff diff --git a/libswscale/version.h b/libswscale/version.h index 0d3b7cf363..0e5583aa47 100644 --- a/libswscale/version.h +++ b/libswscale/version.h @@ -27,7 +27,7 @@ #include "libavutil/version.h" #define LIBSWSCALE_VERSION_MAJOR 6 -#define LIBSWSCALE_VERSION_MINOR 1 +#define LIBSWSCALE_VERSION_MINOR 5 #define LIBSWSCALE_VERSION_MICRO 100 #define LIBSWSCALE_VERSION_INT AV_VERSION_INT(LIBSWSCALE_VERSION_MAJOR, \ diff --git a/libswscale/x86/Makefile b/libswscale/x86/Makefile index bfe383364e..68391494be 100644 --- a/libswscale/x86/Makefile +++ b/libswscale/x86/Makefile @@ -11,6 +11,7 @@ OBJS-$(CONFIG_XMM_CLOBBER_TEST) += x86/w64xmmtest.o X86ASM-OBJS += x86/input.o \ x86/output.o \ x86/scale.o \ + x86/scale_avx2.o \ x86/rgb_2_rgb.o \ x86/yuv_2_rgb.o \ x86/yuv2yuvX.o \ diff --git a/libswscale/x86/input.asm b/libswscale/x86/input.asm index af9afcaa53..fcdfe2fcd8 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 ;----------------------------------------------------------------------------- @@ -738,3 +762,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 52cf9f2c2e..1e498fddf6 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, \ @@ -549,3 +591,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/scale_avx2.asm b/libswscale/x86/scale_avx2.asm new file mode 100644 index 0000000000..20acdbd633 --- /dev/null +++ b/libswscale/x86/scale_avx2.asm @@ -0,0 +1,114 @@ +;****************************************************************************** +;* x86-optimized horizontal line scaling functions +;* Copyright 2020 Google LLC +;* Copyright (c) 2011 Ronald S. Bultje +;* +;* This file is part of FFmpeg. +;* +;* FFmpeg is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* FFmpeg is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with FFmpeg; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "libavutil/x86/x86util.asm" + +SECTION_RODATA 32 + +swizzle: dd 0, 4, 1, 5, 2, 6, 3, 7 +four: times 8 dd 4 + +SECTION .text + +;----------------------------------------------------------------------------- +; horizontal line scaling +; +; void hscale8to15__ +; (SwsContext *c, int16_t *dst, +; int dstW, const uint8_t *src, +; const int16_t *filter, +; const int32_t *filterPos, int filterSize); +; +; Scale one horizontal line. Input is 8-bit width Filter is 14 bits. Output is +; 15 bits (in int16_t). Each output pixel is generated from $filterSize input +; pixels, the position of the first pixel is given in filterPos[nOutputPixel]. +;----------------------------------------------------------------------------- + +%macro SCALE_FUNC 1 +cglobal hscale8to15_%1, 7, 9, 16, pos0, dst, w, srcmem, filter, fltpos, fltsize, count, inner + pxor m0, m0 + mova m15, [swizzle] + xor countq, countq + movsxd wq, wd +%ifidn %1, X4 + mova m14, [four] + shr fltsized, 2 +%endif +.loop: + movu m1, [fltposq] + movu m2, [fltposq+32] +%ifidn %1, X4 + pxor m9, m9 + pxor m10, m10 + pxor m11, m11 + pxor m12, m12 + xor innerq, innerq +.innerloop: +%endif + vpcmpeqd m13, m13 + vpgatherdd m3,[srcmemq + m1], m13 + vpcmpeqd m13, m13 + vpgatherdd m4,[srcmemq + m2], m13 + vpunpcklbw m5, m3, m0 + vpunpckhbw m6, m3, m0 + vpunpcklbw m7, m4, m0 + vpunpckhbw m8, m4, m0 + vpmaddwd m5, m5, [filterq] + vpmaddwd m6, m6, [filterq + 32] + vpmaddwd m7, m7, [filterq + 64] + vpmaddwd m8, m8, [filterq + 96] + add filterq, 0x80 +%ifidn %1, X4 + paddd m9, m5 + paddd m10, m6 + paddd m11, m7 + paddd m12, m8 + paddd m1, m14 + paddd m2, m14 + add innerq, 1 + cmp innerq, fltsizeq + jl .innerloop + vphaddd m5, m9, m10 + vphaddd m6, m11, m12 +%else + vphaddd m5, m5, m6 + vphaddd m6, m7, m8 +%endif + vpsrad m5, 7 + vpsrad m6, 7 + vpackssdw m5, m5, m6 + vpermd m5, m15, m5 + vmovdqu [dstq + countq * 2], m5 + add fltposq, 0x40 + add countq, 0x10 + cmp countq, wq + jl .loop +REP_RET +%endmacro + +%if ARCH_X86_64 +%if HAVE_AVX2_EXTERNAL +INIT_YMM avx2 +SCALE_FUNC 4 +SCALE_FUNC X4 +%endif +%endif diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 0848a31461..3cf0c419fd 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -276,6 +276,9 @@ SCALE_FUNCS_SSE(sse2); SCALE_FUNCS_SSE(ssse3); SCALE_FUNCS_SSE(sse4); +SCALE_FUNC(4, 8, 15, avx2); +SCALE_FUNC(X4, 8, 15, avx2); + #define VSCALEX_FUNC(size, opt) \ void ff_yuv2planeX_ ## size ## _ ## opt(const int16_t *filter, int filterSize, \ const int16_t **src, uint8_t *dest, int dstW, \ @@ -350,6 +353,117 @@ void ff_yuv2 ## fmt ## cX_ ## opt(enum AVPixelFormat format, const uint8_t *dith YUV2NV_DECL(nv12, avx2); YUV2NV_DECL(nv21, avx2); + +#define YUV2GBRP_FN_DECL(fmt, opt) \ +void ff_yuv2##fmt##_full_X_ ##opt(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) + +#define YUV2GBRP_DECL(opt) \ +YUV2GBRP_FN_DECL(gbrp, opt); \ +YUV2GBRP_FN_DECL(gbrap, opt); \ +YUV2GBRP_FN_DECL(gbrp9le, opt); \ +YUV2GBRP_FN_DECL(gbrp10le, opt); \ +YUV2GBRP_FN_DECL(gbrap10le, opt); \ +YUV2GBRP_FN_DECL(gbrp12le, opt); \ +YUV2GBRP_FN_DECL(gbrap12le, opt); \ +YUV2GBRP_FN_DECL(gbrp14le, opt); \ +YUV2GBRP_FN_DECL(gbrp16le, opt); \ +YUV2GBRP_FN_DECL(gbrap16le, opt); \ +YUV2GBRP_FN_DECL(gbrpf32le, opt); \ +YUV2GBRP_FN_DECL(gbrapf32le, opt); \ +YUV2GBRP_FN_DECL(gbrp9be, opt); \ +YUV2GBRP_FN_DECL(gbrp10be, opt); \ +YUV2GBRP_FN_DECL(gbrap10be, opt); \ +YUV2GBRP_FN_DECL(gbrp12be, opt); \ +YUV2GBRP_FN_DECL(gbrap12be, opt); \ +YUV2GBRP_FN_DECL(gbrp14be, opt); \ +YUV2GBRP_FN_DECL(gbrp16be, opt); \ +YUV2GBRP_FN_DECL(gbrap16be, opt); \ +YUV2GBRP_FN_DECL(gbrpf32be, opt); \ +YUV2GBRP_FN_DECL(gbrapf32be, opt); + +YUV2GBRP_DECL(sse2); +YUV2GBRP_DECL(sse4); +YUV2GBRP_DECL(avx2); + +#define INPUT_PLANAR_RGB_Y_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_y_##opt(uint8_t *dst, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + +#define INPUT_PLANAR_RGB_UV_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_uv_##opt(uint8_t *dstU, uint8_t *dstV, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + +#define INPUT_PLANAR_RGB_A_FN_DECL(fmt, opt) \ +void ff_planar_##fmt##_to_a_##opt(uint8_t *dst, \ + const uint8_t *src[4], int w, int32_t *rgb2yuv) + + +#define INPUT_PLANAR_RGBXX_A_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_A_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_A_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_Y_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_Y_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt) \ +INPUT_PLANAR_RGB_UV_FN_DECL(fmt##le, opt); \ +INPUT_PLANAR_RGB_UV_FN_DECL(fmt##be, opt); + +#define INPUT_PLANAR_RGBXX_YUVA_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(fmt, opt); + +#define INPUT_PLANAR_RGBXX_YUV_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_Y_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); + +#define INPUT_PLANAR_RGBXX_UVA_DECL(fmt, opt) \ +INPUT_PLANAR_RGBXX_UV_DECL(fmt, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(fmt, opt); + +#define INPUT_PLANAR_RGB_A_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_A_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_A_DECL(rgbf32, opt); + +#define INPUT_PLANAR_RGB_Y_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_Y_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb9, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb14, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_Y_DECL(rgbf32, opt); + +#define INPUT_PLANAR_RGB_UV_ALL_DECL(opt) \ +INPUT_PLANAR_RGB_UV_FN_DECL(rgb, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb9, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb10, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb12, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb14, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgb16, opt); \ +INPUT_PLANAR_RGBXX_UV_DECL(rgbf32, opt); + +INPUT_PLANAR_RGBXX_Y_DECL(rgbf32, sse2); +INPUT_PLANAR_RGB_UV_ALL_DECL(sse2); +INPUT_PLANAR_RGB_A_ALL_DECL(sse2); + +INPUT_PLANAR_RGB_Y_ALL_DECL(sse4); +INPUT_PLANAR_RGB_UV_ALL_DECL(sse4); +INPUT_PLANAR_RGBXX_A_DECL(rgbf32, sse4); + +INPUT_PLANAR_RGB_Y_ALL_DECL(avx2); +INPUT_PLANAR_RGB_UV_ALL_DECL(avx2); +INPUT_PLANAR_RGB_A_ALL_DECL(avx2); #endif av_cold void ff_sws_init_swscale_x86(SwsContext *c) @@ -414,14 +528,14 @@ av_cold void ff_sws_init_swscale_x86(SwsContext *c) #define ASSIGN_VSCALEX_FUNC(vscalefn, opt, do_16_case, condition_8bit) \ switch(c->dstBpc){ \ case 16: do_16_case; break; \ - case 10: if (!isBE(c->dstFormat) && c->dstFormat != AV_PIX_FMT_P010LE) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ + case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ 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) \ switch(c->dstBpc){ \ case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt1; break; \ - case 10: if (!isBE(c->dstFormat) && c->dstFormat != AV_PIX_FMT_P010LE && opt2chk) vscalefn = ff_yuv2plane1_10_ ## opt2; 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; \ default: av_assert0(c->dstBpc>8); \ @@ -568,6 +682,22 @@ switch(c->dstBpc){ \ } #if ARCH_X86_64 +#define ASSIGN_AVX2_SCALE_FUNC(hscalefn, filtersize) \ + switch (filtersize) { \ + case 4: hscalefn = ff_hscale8to15_4_avx2; break; \ + default: hscalefn = ff_hscale8to15_X4_avx2; break; \ + break; \ + } + + if (EXTERNAL_AVX2_FAST(cpu_flags) && !(cpu_flags & AV_CPU_FLAG_SLOW_GATHER)) { + if ((c->srcBpc == 8) && (c->dstBpc <= 14)) { + if (c->chrDstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hcScale, c->hChrFilterSize); + if (c->dstW % 16 == 0) + ASSIGN_AVX2_SCALE_FUNC(c->hyScale, c->hLumFilterSize); + } + } + if (EXTERNAL_AVX2_FAST(cpu_flags)) { switch (c->dstFormat) { case AV_PIX_FMT_NV12: @@ -582,5 +712,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/yuv2rgb.c b/libswscale/yuv2rgb.c index 353de2f822..76232cb364 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -145,8 +145,8 @@ const int *sws_getCoefficients(int colorspace) dst_type av_unused *r, *g, *b; \ const uint8_t *py_1 = src[0] + y * srcStride[0]; \ const uint8_t *py_2 = py_1 + srcStride[0]; \ - const uint8_t *pu = src[1] + (y >> 1) * srcStride[1]; \ - const uint8_t *pv = src[2] + (y >> 1) * srcStride[2]; \ + const uint8_t av_unused *pu = src[1] + (y >> 1) * srcStride[1]; \ + const uint8_t av_unused *pv = src[2] + (y >> 1) * srcStride[2]; \ const uint8_t av_unused *pa_1, *pa_2; \ unsigned int h_size = c->dstW >> 3; \ if (alpha) { \ diff --git a/tests/Makefile b/tests/Makefile index 1e0345b163..87807ed31f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,3 +1,4 @@ + THREADS = 1 VREF = tests/vsynth1/00.pgm AREF = tests/data/asynth1.sw @@ -10,8 +11,7 @@ FFMPEG=ffmpeg$(PROGSSUF)$(EXESUF) $(AREF): CMP= APITESTSDIR := tests/api -DNNTESTSDIR := tests/dnn -FATE_OUTDIRS = tests/data tests/data/fate tests/data/filtergraphs tests/data/lavf tests/data/lavf-fate tests/data/pixfmt tests/vsynth1 $(APITESTSDIR) $(DNNTESTSDIR) +FATE_OUTDIRS = tests/data tests/data/fate tests/data/filtergraphs tests/data/lavf tests/data/lavf-fate tests/data/pixfmt tests/vsynth1 $(APITESTSDIR) OUTDIRS += $(FATE_OUTDIRS) $(VREF): tests/videogen$(HOSTEXESUF) | tests/vsynth1 @@ -40,7 +40,7 @@ tests/test_copy.ffmeta: tests/data $(M)cp -f $(SRC_PATH)/tests/test.ffmeta tests/test_copy.ffmeta tests/data/ffprobe-test.nut: ffmpeg$(PROGSSUF)$(EXESUF) tests/test_copy.ffmeta - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=sin(400*PI*2*t):d=0.125[out0]; testsrc=d=0.125[out1]; testsrc=s=100x100:d=0.125[out2]" \ -f ffmetadata -i $(TARGET_PATH)/tests/test_copy.ffmeta \ -flags +bitexact -fflags +bitexact -map 0:0 -map 0:1 -map 0:2 -map_metadata 1 \ @@ -96,7 +96,6 @@ CONFIG_LARGE_TESTS:= endif include $(SRC_PATH)/$(APITESTSDIR)/Makefile -include $(SRC_PATH)/$(DNNTESTSDIR)/Makefile include $(SRC_PATH)/tests/fate/acodec.mak include $(SRC_PATH)/tests/fate/vcodec.mak diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile index 4ef5fa87da..f768b1144e 100644 --- a/tests/checkasm/Makefile +++ b/tests/checkasm/Makefile @@ -45,7 +45,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/av_tx.c b/tests/checkasm/av_tx.c index 178fb61972..9d3823e8ed 100644 --- a/tests/checkasm/av_tx.c +++ b/tests/checkasm/av_tx.c @@ -22,6 +22,8 @@ #include "checkasm.h" +#include + #define EPS 0.00005 #define SCALE_NOOP(x) (x) @@ -41,6 +43,16 @@ static const int check_lens[] = { 2, 4, 8, 16, 32, 64, 1024, 16384, }; +static AVTXContext *tx_refs[6 /*AVTXType*/][FF_ARRAY_ELEMS(check_lens)]; +static int init = 0; + +static void free_tx_refs(void) +{ + for (int i = 0; i < FF_ARRAY_ELEMS(tx_refs); i++) + for (int j = 0; j < FF_ARRAY_ELEMS(*tx_refs); j++) + av_tx_uninit(&tx_refs[i][j]); +} + #define CHECK_TEMPLATE(PREFIX, TYPE, DATA_TYPE, SCALE, LENGTHS, CHECK_EXPRESSION) \ do { \ int err; \ @@ -59,24 +71,26 @@ static const int check_lens[] = { } \ \ if (check_func(fn, PREFIX "_%i", len)) { \ + AVTXContext *tx_ref = tx_refs[TYPE][i]; \ + if (!tx_ref) \ + tx_ref = tx; \ num_checks++; \ last_check = len; \ - call_ref(tx, out_ref, in, sizeof(DATA_TYPE)); \ - call_new(tx, out_new, in, sizeof(DATA_TYPE)); \ + call_ref(tx_ref, out_ref, in, sizeof(DATA_TYPE)); \ + call_new(tx, out_new, in, sizeof(DATA_TYPE)); \ if (CHECK_EXPRESSION) { \ fail(); \ + av_tx_uninit(&tx); \ break; \ } \ bench_new(tx, out_new, in, sizeof(DATA_TYPE)); \ + av_tx_uninit(&tx_refs[TYPE][i]); \ + tx_refs[TYPE][i] = tx; \ + } else { \ + av_tx_uninit(&tx); \ } \ - \ - av_tx_uninit(&tx); \ - fn = NULL; \ } \ \ - av_tx_uninit(&tx); \ - fn = NULL; \ - \ if (num_checks == 1) \ report(PREFIX "_%i", last_check); \ else if (num_checks) \ @@ -105,4 +119,9 @@ void checkasm_check_av_tx(void) av_free(in); av_free(out_ref); av_free(out_new); + + if (!init) { + init = 1; + atexit(free_tx_refs); + } } diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c index b1353f7cbe..f74125e810 100644 --- a/tests/checkasm/checkasm.c +++ b/tests/checkasm/checkasm.c @@ -183,6 +183,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 @@ -236,6 +237,9 @@ static const struct { { "FMA4", "fma4", AV_CPU_FLAG_FMA4 }, { "AVX2", "avx2", AV_CPU_FLAG_AVX2 }, { "AVX-512", "avx512", AV_CPU_FLAG_AVX512 }, +#elif ARCH_LOONGARCH + { "LSX", "lsx", AV_CPU_FLAG_LSX }, + { "LASX", "lasx", AV_CPU_FLAG_LASX }, #endif { NULL } }; diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h index 68b0697d3e..c3192d8c23 100644 --- a/tests/checkasm/checkasm.h +++ b/tests/checkasm/checkasm.h @@ -72,6 +72,7 @@ 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); diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c new file mode 100644 index 0000000000..848e5366ad --- /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 1e7ffe0fff..3c0a083b42 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -134,13 +134,13 @@ static void check_yuv2yuvX(void) } #undef SRC_PIXELS -#define SRC_PIXELS 128 +#define SRC_PIXELS 512 static void check_hscale(void) { #define MAX_FILTER_WIDTH 40 -#define FILTER_SIZES 5 - static const int filter_sizes[FILTER_SIZES] = { 4, 8, 16, 32, 40 }; +#define FILTER_SIZES 6 + static const int filter_sizes[FILTER_SIZES] = { 4, 8, 12, 16, 32, 40 }; #define HSCALE_PAIRS 2 static const int hscale_pairs[HSCALE_PAIRS][2] = { @@ -159,6 +159,8 @@ static void check_hscale(void) // padded LOCAL_ALIGNED_32(int16_t, filter, [SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH]); LOCAL_ALIGNED_32(int32_t, filterPos, [SRC_PIXELS]); + LOCAL_ALIGNED_32(int16_t, filterAvx2, [SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH]); + LOCAL_ALIGNED_32(int32_t, filterPosAvx, [SRC_PIXELS]); // The dst parameter here is either int16_t or int32_t but we use void* to // just cover both cases. @@ -166,6 +168,8 @@ static void check_hscale(void) const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize); + int cpu_flags = av_get_cpu_flags(); + ctx = sws_alloc_context(); if (sws_init_context(ctx, NULL, NULL) < 0) fail(); @@ -179,9 +183,11 @@ static void check_hscale(void) ctx->srcBpc = hscale_pairs[hpi][0]; ctx->dstBpc = hscale_pairs[hpi][1]; ctx->hLumFilterSize = ctx->hChrFilterSize = width; + ctx->dstW = ctx->chrDstW = SRC_PIXELS; 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: @@ -210,16 +216,19 @@ static void check_hscale(void) 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); 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])); call_ref(NULL, dst0, SRC_PIXELS, src, filter, filterPos, width); - call_new(NULL, dst1, 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, filterPos, width); + bench_new(NULL, dst0, SRC_PIXELS, src, filter, filterPosAvx, width); } } } diff --git a/tests/dnn/.gitignore b/tests/dnn/.gitignore deleted file mode 100644 index 03b04d6653..0000000000 --- a/tests/dnn/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -/dnn-layer-conv2d-test -/dnn-layer-depth2space-test -/dnn-layer-maximum-test -/dnn-layer-pad-test -/dnn-layer-mathbinary-test -/dnn-layer-mathunary-test -/dnn-layer-avgpool-test -/dnn-layer-dense-test diff --git a/tests/dnn/Makefile b/tests/dnn/Makefile deleted file mode 100644 index ef827520de..0000000000 --- a/tests/dnn/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -DNNTESTPROGS += dnn-layer-pad -DNNTESTPROGS += dnn-layer-conv2d -DNNTESTPROGS += dnn-layer-depth2space -DNNTESTPROGS += dnn-layer-dense -DNNTESTPROGS += dnn-layer-mathbinary -DNNTESTPROGS += dnn-layer-maximum -DNNTESTPROGS += dnn-layer-mathunary -DNNTESTPROGS += dnn-layer-avgpool - -DNNTESTOBJS := $(DNNTESTOBJS:%=$(DNNTESTSDIR)%) $(DNNTESTPROGS:%=$(DNNTESTSDIR)/%-test.o) -DNNTESTPROGS := $(DNNTESTPROGS:%=$(DNNTESTSDIR)/%-test$(EXESUF)) --include $(wildcard $(DNNTESTOBJS:.o=.d)) - -$(DNNTESTPROGS): %$(EXESUF): %.o $(FF_STATIC_DEP_LIBS) - $(LD) $(LDFLAGS) $(LDEXEFLAGS) $(LD_O) $(filter %.o,$^) $(FF_STATIC_DEP_LIBS) $(EXTRALIBS-avcodec) $(EXTRALIBS-avfilter) $(EXTRALIBS-avformat) $(EXTRALIBS-avutil) $(EXTRALIBS-swresample) $(EXTRALIBS) - -testclean:: - $(RM) $(addprefix $(DNNTESTSDIR)/,$(CLEANSUFFIXES) *-test$(EXESUF)) diff --git a/tests/fate/amrnb.mak b/tests/fate/amrnb.mak index c0feec25dc..f4f74f14d9 100644 --- a/tests/fate/amrnb.mak +++ b/tests/fate/amrnb.mak @@ -30,7 +30,13 @@ 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 ALLYES, FILE_PROTOCOL AMR_DEMUXER AMR_PARSER \ + AMR_MUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += 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 b93835d76d..8450c28bba 100644 --- a/tests/fate/amrwb.mak +++ b/tests/fate/amrwb.mak @@ -41,7 +41,13 @@ 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 ALLYES, FILE_PROTOCOL MOV_DEMUXER AMR_PARSER AMR_MUXER \ + AMR_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += 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/checkasm.mak b/tests/fate/checkasm.mak index 6e7edbe655..6db8f09d12 100644 --- a/tests/fate/checkasm.mak +++ b/tests/fate/checkasm.mak @@ -26,6 +26,7 @@ FATE_CHECKASM = fate-checkasm-aacpsdsp \ 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 \ diff --git a/tests/fate/dnn.mak b/tests/fate/dnn.mak index ef07ee45f8..a30a2976d9 100644 --- a/tests/fate/dnn.mak +++ b/tests/fate/dnn.mak @@ -1,41 +1,43 @@ +DNNTESTSDIR := libavfilter/tests + FATE_DNN += fate-dnn-layer-pad -fate-dnn-layer-pad: $(DNNTESTSDIR)/dnn-layer-pad-test$(EXESUF) -fate-dnn-layer-pad: CMD = run $(DNNTESTSDIR)/dnn-layer-pad-test$(EXESUF) +fate-dnn-layer-pad: $(DNNTESTSDIR)/dnn-layer-pad$(EXESUF) +fate-dnn-layer-pad: CMD = run $(DNNTESTSDIR)/dnn-layer-pad$(EXESUF) fate-dnn-layer-pad: CMP = null FATE_DNN += fate-dnn-layer-conv2d -fate-dnn-layer-conv2d: $(DNNTESTSDIR)/dnn-layer-conv2d-test$(EXESUF) -fate-dnn-layer-conv2d: CMD = run $(DNNTESTSDIR)/dnn-layer-conv2d-test$(EXESUF) +fate-dnn-layer-conv2d: $(DNNTESTSDIR)/dnn-layer-conv2d$(EXESUF) +fate-dnn-layer-conv2d: CMD = run $(DNNTESTSDIR)/dnn-layer-conv2d$(EXESUF) fate-dnn-layer-conv2d: CMP = null FATE_DNN += fate-dnn-layer-dense -fate-dnn-layer-dense: $(DNNTESTSDIR)/dnn-layer-dense-test$(EXESUF) -fate-dnn-layer-dense: CMD = run $(DNNTESTSDIR)/dnn-layer-dense-test$(EXESUF) +fate-dnn-layer-dense: $(DNNTESTSDIR)/dnn-layer-dense$(EXESUF) +fate-dnn-layer-dense: CMD = run $(DNNTESTSDIR)/dnn-layer-dense$(EXESUF) fate-dnn-layer-dense: CMP = null FATE_DNN += fate-dnn-layer-depth2space -fate-dnn-layer-depth2space: $(DNNTESTSDIR)/dnn-layer-depth2space-test$(EXESUF) -fate-dnn-layer-depth2space: CMD = run $(DNNTESTSDIR)/dnn-layer-depth2space-test$(EXESUF) +fate-dnn-layer-depth2space: $(DNNTESTSDIR)/dnn-layer-depth2space$(EXESUF) +fate-dnn-layer-depth2space: CMD = run $(DNNTESTSDIR)/dnn-layer-depth2space$(EXESUF) fate-dnn-layer-depth2space: CMP = null FATE_DNN += fate-dnn-layer-mathbinary -fate-dnn-layer-mathbinary: $(DNNTESTSDIR)/dnn-layer-mathbinary-test$(EXESUF) -fate-dnn-layer-mathbinary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathbinary-test$(EXESUF) +fate-dnn-layer-mathbinary: $(DNNTESTSDIR)/dnn-layer-mathbinary$(EXESUF) +fate-dnn-layer-mathbinary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathbinary$(EXESUF) fate-dnn-layer-mathbinary: CMP = null FATE_DNN += fate-dnn-layer-maximum -fate-dnn-layer-maximum: $(DNNTESTSDIR)/dnn-layer-maximum-test$(EXESUF) -fate-dnn-layer-maximum: CMD = run $(DNNTESTSDIR)/dnn-layer-maximum-test$(EXESUF) +fate-dnn-layer-maximum: $(DNNTESTSDIR)/dnn-layer-maximum$(EXESUF) +fate-dnn-layer-maximum: CMD = run $(DNNTESTSDIR)/dnn-layer-maximum$(EXESUF) fate-dnn-layer-maximum: CMP = null FATE_DNN += fate-dnn-layer-mathunary -fate-dnn-layer-mathunary: $(DNNTESTSDIR)/dnn-layer-mathunary-test$(EXESUF) -fate-dnn-layer-mathunary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathunary-test$(EXESUF) +fate-dnn-layer-mathunary: $(DNNTESTSDIR)/dnn-layer-mathunary$(EXESUF) +fate-dnn-layer-mathunary: CMD = run $(DNNTESTSDIR)/dnn-layer-mathunary$(EXESUF) fate-dnn-layer-mathunary: CMP = null FATE_DNN += fate-dnn-layer-avgpool -fate-dnn-layer-avgpool: $(DNNTESTSDIR)/dnn-layer-avgpool-test$(EXESUF) -fate-dnn-layer-avgpool: CMD = run $(DNNTESTSDIR)/dnn-layer-avgpool-test$(EXESUF) +fate-dnn-layer-avgpool: $(DNNTESTSDIR)/dnn-layer-avgpool$(EXESUF) +fate-dnn-layer-avgpool: CMD = run $(DNNTESTSDIR)/dnn-layer-avgpool$(EXESUF) fate-dnn-layer-avgpool: CMP = null FATE-$(CONFIG_DNN) += $(FATE_DNN) diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 4dfb77d250..0b00bb5b23 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -32,7 +32,7 @@ fate-ffmpeg-filter_complex_audio: CMD = framecrc -auto_conversion_filters -filte # Ticket 6375, use case of NoX FATE_SAMPLES_FFMPEG-$(call ALLYES, MOV_DEMUXER PNG_DECODER ALAC_DECODER PCM_S16LE_ENCODER RAWVIDEO_ENCODER) += fate-ffmpeg-attached_pics -fate-ffmpeg-attached_pics: CMD = threads=2 framecrc -i $(TARGET_SAMPLES)/lossless-audio/inside.m4a -c:a pcm_s16le -max_muxing_queue_size 16 -af aresample +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-$(CONFIG_COLORKEY_FILTER) += fate-ffmpeg-filter_colorkey fate-ffmpeg-filter_colorkey: tests/data/filtergraphs/colorkey @@ -54,7 +54,7 @@ fate-sub2video: CMD = framecrc -auto_conversion_filters \ -f rawvideo -r 5 -s 352x288 -pix_fmt yuv420p -i $(TARGET_PATH)/tests/data/vsynth_lena.yuv \ -ss 132 -i $(TARGET_SAMPLES)/sub/vobsub.idx \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:0]scale=720:480[v]\;[v][1:0]overlay[v2]" \ - -map "[v2]" -c:v rawvideo -map 1:s -c:s dvdsub + -map "[v2]" -c:v rawvideo -threads 1 -map 1:s -c:s dvdsub # Very basic sub2video example, decode and convert to AVFrame with sub2video. # Attempt to not touch timestamps. @@ -63,7 +63,7 @@ fate-sub2video_basic: CMD = framecrc -auto_conversion_filters \ -i $(TARGET_SAMPLES)/sub/vobsub.idx \ -vsync passthrough -copyts \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ - -c:v rawvideo + -c:v rawvideo -threads 1 # Time-limited run with a sample that doesn't require seeking and # contains samples within the initial period. @@ -73,7 +73,7 @@ fate-sub2video_time_limited: CMD = framecrc -auto_conversion_filters \ -vsync passthrough -copyts \ -t 15 \ -filter_complex "sws_flags=+accurate_rnd+bitexact\;[0:s:0]scale" \ - -c:v rawvideo + -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-unknown_layout-pcm: $(AREF) @@ -86,6 +86,13 @@ 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_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-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 @@ -131,12 +138,39 @@ FATE_STREAMCOPY-$(CONFIG_FLV_DEMUXER) += fate-ffmpeg-streamloop fate-ffmpeg-streamloop: $(SAMPLES)/flv/streamloop.flv 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 +tests/data/audio_shorter_than_video.nut: tests/data/vsynth_lena.yuv +tests/data/audio_shorter_than_video.nut: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ + -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 \ + -f lavfi -i "sine=1000:d=1" \ + -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-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-rgb24-mkv: CMD = transcode "mov" $(TARGET_SAMPLES)/qtrle/aletrek-rle.mov\ - matroska "-c:v rawvideo -pix_fmt rgb24 -allow_raw_vfw 1 -frames:v 1" + 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 diff --git a/tests/fate/filter-audio.mak b/tests/fate/filter-audio.mak index db70f26438..f97318476f 100644 --- a/tests/fate/filter-audio.mak +++ b/tests/fate/filter-audio.mak @@ -201,7 +201,7 @@ fate-filter-compand: CMD = framecrc -auto_conversion_filters -i $(SRC) -frames:a tests/data/hls-list.m3u8: TAG = GEN tests/data/hls-list.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f segment -segment_time 10 -map 0 -flags +bitexact -codec:a mp2fixed \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/hls-out-%03d.ts 2>/dev/null @@ -211,10 +211,10 @@ fate-filter-hls: CMD = framecrc -flags +bitexact -i $(TARGET_PATH)/tests/data/hl tests/data/hls-list-append.m3u8: TAG = GEN tests/data/hls-list-append.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f segment -segment_time 10 -map 0 -flags +bitexact -codec:a mp2fixed \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/hls-append-out-%03d.ts 2>/dev/null; \ - $(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 10 -map 0 -flags +bitexact \ -hls_flags append_list -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls-append-out-%03d.ts \ $(TARGET_PATH)/tests/data/hls-list-append.m3u8 2>/dev/null diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 16f24a8422..7df79c70e9 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -677,7 +677,7 @@ fate-filter-tile: CMD = video_filter "tile=3x3:nb_frames=5:padding=7:margin=2" tests/pixfmts.mak: TAG = GEN tests/pixfmts.mak: ffmpeg$(PROGSSUF)$(EXESUF) | tests $(M)printf "PIXFMTS = " > $@ - $(Q)$(TARGET_EXEC) $(TARGET_PATH)/$< -pix_fmts list 2> /dev/null | awk 'NR > 8 && /^IO/ { printf $$2 " " }' >> $@ + $(Q)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin -pix_fmts list 2> /dev/null | awk 'NR > 8 && /^IO/ { printf $$2 " " }' >> $@ $(Q)printf "\n" >> $@ RUNNING_PIXFMTS_TESTS := $(filter check fate fate-list fate-filter fate-vfilter fate-filter-pixdesc%,$(MAKECMDGOALS)) @@ -838,7 +838,7 @@ fate-filter-metadata-avf-aphase-meter-out-of-phase: CMD = run $(FILTER_METADATA_ tests/data/file4560-override2rotate0.mov: TAG = GEN tests/data/file4560-override2rotate0.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(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 ALLYES, MOV_DEMUXER H264_DECODER AAC_FIXED_DECODER PCM_S16LE_ENCODER MOV_MUXER) += fate-filter-meta-4560-rotate0 diff --git a/tests/fate/fits.mak b/tests/fate/fits.mak index 8c2995a4c6..f16fc83266 100644 --- a/tests/fate/fits.mak +++ b/tests/fate/fits.mak @@ -1,6 +1,6 @@ tests/data/fits-multi.fits: TAG = GEN tests/data/fits-multi.fits: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/gif/m4nb.gif \ -y $(TARGET_PATH)/$(@) 2>/dev/null @@ -14,7 +14,7 @@ map.tests/data/lena-gbrap16le.fits := 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)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/png1/lena-$(map.$(@)).png \ -y $(TARGET_PATH)/$(@) 2>/dev/null diff --git a/tests/fate/flvenc.mak b/tests/fate/flvenc.mak index 4fdeeff4c1..9682f4a2ba 100644 --- a/tests/fate/flvenc.mak +++ b/tests/fate/flvenc.mak @@ -1,6 +1,6 @@ tests/data/add_keyframe_index.flv: TAG = GEN tests/data/add_keyframe_index.flv: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(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; diff --git a/tests/fate/h264.mak b/tests/fate/h264.mak index e034e6ae0f..e075b6f67f 100644 --- a/tests/fate/h264.mak +++ b/tests/fate/h264.mak @@ -342,7 +342,7 @@ fate-h264-conformance-frext-freh7_b: CMD = framecrc -i $(TARGET_SAM fate-h264-conformance-frext-frext01_jvc_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT01_JVC_D.264 fate-h264-conformance-frext-frext02_jvc_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FREXT02_JVC_C.264 fate-h264-conformance-frext-frext1_panasonic_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt1_Panasonic.avc -fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc -vsync 0 +fate-h264-conformance-frext-frext2_panasonic_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt2_Panasonic.avc -vsync passthrough fate-h264-conformance-frext-frext3_panasonic_d: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt3_Panasonic.avc fate-h264-conformance-frext-frext4_panasonic_a: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt4_Panasonic.avc fate-h264-conformance-frext-frext_mmco4_sony_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/FRExt_MMCO4_Sony_B.264 @@ -361,7 +361,7 @@ fate-h264-conformance-frext-hpcadq_brcm_b: CMD = framecrc -i $(TARGET_SAM fate-h264-conformance-frext-hpcafl_bcrm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFL_BRCM_C.264 fate-h264-conformance-frext-hpcaflnl_bcrm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAFLNL_BRCM_C.264 fate-h264-conformance-frext-hpcalq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCALQ_BRCM_B.264 -fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 -vsync 0 +fate-h264-conformance-frext-hpcamapalq_bcrm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMAPALQ_BRCM_B.264 -vsync passthrough fate-h264-conformance-frext-hpcamolq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAMOLQ_BRCM_B.264 fate-h264-conformance-frext-hpcanl_brcm_c: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCANL_BRCM_C.264 fate-h264-conformance-frext-hpcaq2lq_brcm_b: CMD = framecrc -i $(TARGET_SAMPLES)/h264-conformance/FRext/HPCAQ2LQ_BRCM_B.264 diff --git a/tests/fate/hap.mak b/tests/fate/hap.mak index 1582971a6e..ba921798cc 100644 --- a/tests/fate/hap.mak +++ b/tests/fate/hap.mak @@ -46,13 +46,13 @@ fate-hapqa-extract-snappy16-to-hapalphaonly: CMD = framecrc -i $(TARGET_SAMPLES) #Test bsf conversion and mov tests/data/hapq_nosnappy.mov: TAG = GEN tests/data/hapq_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=color \ -tag:v HapY -metadata:s:v:0 encoder="HAPQ" $(TARGET_PATH)/$@ -y 2>/dev/null tests/data/hapalphaonly_nosnappy.mov: TAG = GEN tests/data/hapalphaonly_nosnappy.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/hap/HAPQA_NoSnappy_127x1.mov -nostdin -c:v copy -bsf:v hapqa_extract=texture=alpha \ -tag:v HapA -metadata:s:v:0 encoder="HAPAlpha Only" $(TARGET_PATH)/$@ -y 2>/dev/null diff --git a/tests/fate/hevc.mak b/tests/fate/hevc.mak index f6ea1df9a5..f294cff414 100644 --- a/tests/fate/hevc.mak +++ b/tests/fate/hevc.mak @@ -239,12 +239,12 @@ $(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-paramchange-yuv420p-yuv420p10: CMD = framecrc -vsync 0 -i $(TARGET_SAMPLES)/hevc/paramchange_yuv420p_yuv420p10.hevc -sws_flags area+accurate_rnd+bitexact +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 tests/data/hevc-mp4.mov: TAG = GEN tests/data/hevc-mp4.mov: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(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 @@ -273,6 +273,9 @@ FATE_HEVC_FFPROBE-$(call DEMDEC, 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-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-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 diff --git a/tests/fate/hlsenc.mak b/tests/fate/hlsenc.mak index aff81a83fc..7df74f1f63 100644 --- a/tests/fate/hlsenc.mak +++ b/tests/fate/hlsenc.mak @@ -1,6 +1,6 @@ tests/data/live_no_endlist.m3u8: TAG = GEN tests/data/live_no_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -v verbose -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -hls_flags omit_endlist -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_no_endlist_%03d.ts \ $(TARGET_PATH)/tests/data/live_no_endlist.m3u8 2>/dev/null @@ -14,7 +14,7 @@ fate-hls-live-no-endlist: REF = e038bb8e65d4c1745b9b3ed643e607a3 tests/data/live_last_endlist.m3u8: TAG = GEN tests/data/live_last_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -v verbose -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_last_endlist_%03d.ts \ $(TARGET_PATH)/tests/data/live_last_endlist.m3u8 2>/dev/null @@ -29,7 +29,7 @@ fate-hls-live-last-endlist: REF = 2ca8567092dcf01e37bedd50454d1ab7 tests/data/live_endlist.m3u8: TAG = GEN tests/data/live_endlist.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 3 -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/live_endlist_%d.ts \ $(TARGET_PATH)/tests/data/live_endlist.m3u8 2>/dev/null @@ -43,7 +43,7 @@ fate-hls-live-endlist: REF = e189ce781d9c87882f58e3929455167b tests/data/hls_segment_size.m3u8: TAG = GEN tests/data/hls_segment_size.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_segment_size 300000 -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_segment_size_%d.ts \ $(TARGET_PATH)/tests/data/hls_segment_size.m3u8 2>/dev/null @@ -54,7 +54,7 @@ fate-hls-segment-size: CMD = framecrc -auto_conversion_filters -flags +bitexact tests/data/hls_segment_single.m3u8: TAG = GEN tests/data/hls_segment_single.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_flags single_file -map 0 \ -hls_list_size 0 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_segment_single.ts \ $(TARGET_PATH)/tests/data/hls_segment_single.m3u8 2>/dev/null @@ -65,7 +65,7 @@ fate-hls-segment-single: CMD = framecrc -auto_conversion_filters -flags +bitexac tests/data/hls_init_time.m3u8: TAG = GEN tests/data/hls_init_time.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=11" -f hls -hls_init_time 1 -hls_time 3 -map 0 \ -hls_list_size 5 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_init_time_%d.ts \ $(TARGET_PATH)/tests/data/hls_init_time.m3u8 2>/dev/null @@ -76,7 +76,7 @@ fate-hls-init-time: CMD = framecrc -auto_conversion_filters -flags +bitexact -i tests/data/hls_list_size.m3u8: TAG = GEN tests/data/hls_list_size.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=20" -f hls -hls_time 4 -map 0 \ -hls_list_size 4 -codec:a mp2fixed -hls_segment_filename $(TARGET_PATH)/tests/data/hls_list_size_%d.ts \ $(TARGET_PATH)/tests/data/hls_list_size.m3u8 2>/dev/null @@ -87,7 +87,7 @@ fate-hls-list-size: CMD = framecrc -auto_conversion_filters -flags +bitexact -i tests/data/hls_fmp4.m3u8: TAG = GEN tests/data/hls_fmp4.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -f lavfi -re -i "aevalsrc=cos(2*PI*t)*sin(2*PI*(440+4*t)*t):d=5" -map 0 -codec:a mp2fixed \ -hls_segment_type mpegts -hls_fmp4_init_filename now.mp4 -hls_list_size 0 \ -hls_time 1 -hls_segment_filename "$(TARGET_PATH)/tests/data/hls_fmp4_%d.m4s" \ @@ -99,7 +99,7 @@ fate-hls-fmp4: CMD = framecrc -auto_conversion_filters -flags +bitexact -i $(TAR tests/data/hls_fmp4_ac3.m3u8: TAG = GEN tests/data/hls_fmp4_ac3.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -stream_loop 4 -i $(SAMPLES)/ac3/monsters_inc_5.1_448_small.ac3 -c copy -map 0 \ -hls_segment_type fmp4 -hls_fmp4_init_filename now_ac3.mp4 -hls_list_size 0 \ -hls_time 2 -hls_segment_filename "$(TARGET_PATH)/tests/data/hls_fmp4_ac3_%d.m4s" \ diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak index d1e81284ed..59ff0ebc8d 100644 --- a/tests/fate/libavformat.mak +++ b/tests/fate/libavformat.mak @@ -22,6 +22,10 @@ FATE_LIBAVFORMAT-$(CONFIG_MOV_MUXER) += fate-movenc fate-movenc: libavformat/tests/movenc$(EXESUF) fate-movenc: CMD = run libavformat/tests/movenc$(EXESUF) +FATE_LIBAVFORMAT-$(CONFIG_IMF_DEMUXER) += fate-imf +fate-imf: libavformat/tests/imf$(EXESUF) +fate-imf: CMD = run libavformat/tests/imf$(EXESUF) + FATE_LIBAVFORMAT += $(FATE_LIBAVFORMAT-yes) FATE-$(CONFIG_AVFORMAT) += $(FATE_LIBAVFORMAT) fate-libavformat: $(FATE_LIBAVFORMAT) diff --git a/tests/fate/libswscale.mak b/tests/fate/libswscale.mak index 599d27b0a5..cf9319ec44 100644 --- a/tests/fate/libswscale.mak +++ b/tests/fate/libswscale.mak @@ -15,8 +15,10 @@ fate-sws-slice-bgr0-nv12: CMD = run tools/scale_slice_test$(EXESUF) $(TARGET_SAM fate-sws-slice: $(SWS_SLICE_TEST-yes) $(SWS_SLICE_TEST-yes): tools/scale_slice_test$(EXESUF) $(SWS_SLICE_TEST-yes): REF = /dev/null -FATE_LIBSWSCALE += $(SWS_SLICE_TEST-yes) +FATE_LIBSWSCALE_SAMPLES += $(SWS_SLICE_TEST-yes) FATE_LIBSWSCALE += $(FATE_LIBSWSCALE-yes) +FATE_LIBSWSCALE_SAMPLES += $(FATE_LIBSWSCALE_SAMPLES-yes) FATE-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE) -fate-libswscale: $(FATE_LIBSWSCALE) +FATE_EXTERN-$(CONFIG_SWSCALE) += $(FATE_LIBSWSCALE_SAMPLES) +fate-libswscale: $(FATE_LIBSWSCALE) $(FATE_LIBSWSCALE_SAMPLES) diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index e117a0f6a6..295489d2cc 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -67,6 +67,44 @@ 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" +# 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 ALLYES, FILE_PROTOCOL WAV_DEMUXER PCM_S24LE_DECODER \ + PCM_S24BE_ENCODER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += 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 ALLYES, FILE_PROTOCOL MOV_DEMUXER \ + HEVC_DECODER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER \ + PIPE_PROTOCOL) \ + += 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" + +# 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 ALLYES, FILE_PROTOCOL AVI_DEMUXER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER \ + PIPE_PROTOCOL) += 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 ALLYES, FILE_PROTOCOL MOV_DEMUXER MATROSKA_MUXER \ + MATROSKA_DEMUXER FRAMECRC_MUXER PIPE_PROTOCOL) \ + += 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. diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 5ca992e181..e956380909 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -94,8 +94,8 @@ fate-mov-neg-firstpts-discard: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entri # with negative timestamps (skip_samples is not set for Vorbis, so ffmpeg computes start_time as negative if not specified by demuxer). fate-mov-neg-firstpts-discard-vorbis: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -show_entries stream=start_time -bitexact $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard_vorbis.mp4 -# Makes sure that expected frames are generated for mov_neg_first_pts_discard.mov with -vsync 1 -fate-mov-neg-firstpts-discard-frames: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov -vsync 1 +# Makes sure that expected frames are generated for mov_neg_first_pts_discard.mov with -vsync cfr +fate-mov-neg-firstpts-discard-frames: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_neg_first_pts_discard.mov -vsync cfr # Makes sure that no frame is dropped/duplicated with fps filter due to start_time / duration miscalculations. fate-mov-stream-shorter-than-movie: CMD = framemd5 -flags +bitexact -i $(TARGET_SAMPLES)/mov/mov_stream_shorter_than_movie.mov -vf fps=fps=24 -an diff --git a/tests/fate/mpeg4.mak b/tests/fate/mpeg4.mak index ed6a2fac20..26007f82f0 100644 --- a/tests/fate/mpeg4.mak +++ b/tests/fate/mpeg4.mak @@ -8,7 +8,7 @@ FATE_MPEG4-$(call DEMDEC, H263, H263) := $(addprefix fate-mpeg4-resolution-chang 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-packed: CMD = framecrc -flags +bitexact -idct simple -i $(TARGET_SAMPLES)/mpeg4/packed_bframes.avi -flags +bitexact -fflags +bitexact -vsync 1 +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 DEMDEC, M4V, MPEG4) += fate-m4v fate-m4v-cfr diff --git a/tests/fate/segment.mak b/tests/fate/segment.mak index ddefbed3bd..88866fc9bb 100644 --- a/tests/fate/segment.mak +++ b/tests/fate/segment.mak @@ -1,20 +1,20 @@ tests/data/mp4-to-ts.m3u8: TAG = GEN tests/data/mp4-to-ts.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/h264/interlaced_crop.mp4 \ -f ssegment -segment_time 1 -map 0 -flags +bitexact -codec copy \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/mp4-to-ts-%03d.ts 2>/dev/null tests/data/adts-to-mkv.m3u8: TAG = GEN tests/data/adts-to-mkv.m3u8: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a \ -f segment -segment_time 1 -map 0 -flags +bitexact -codec copy -segment_format_options live=1 \ -segment_list $(TARGET_PATH)/$@ -y $(TARGET_PATH)/tests/data/adts-to-mkv-%03d.mkv 2>/dev/null tests/data/adts-to-mkv-header.mkv: TAG = GEN tests/data/adts-to-mkv-header.mkv: ffmpeg$(PROGSSUF)$(EXESUF) | tests/data - $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< \ + $(M)$(TARGET_EXEC) $(TARGET_PATH)/$< -nostdin \ -i $(TARGET_SAMPLES)/audiomatch/tones_afconvert_16000_mono_aac_lc.m4a \ -f segment -segment_time 1 -map 0 -flags +bitexact -codec copy -segment_format_options live=1 \ -segment_header_filename $(TARGET_PATH)/tests/data/adts-to-mkv-header.mkv \ diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak index 0c89adb0d1..8375cf2898 100644 --- a/tests/fate/subtitles.mak +++ b/tests/fate/subtitles.mak @@ -16,7 +16,7 @@ fate-sub-ass-to-ass-transcode: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/1ede FATE_SUBTITLES_ASS-$(CONFIG_ASS_DEMUXER) += fate-sub-ssa-to-ass-remux fate-sub-ssa-to-ass-remux: CMD = fmtstdout ass -i $(TARGET_SAMPLES)/sub/a9-misc.ssa -c copy -FATE_SUBTITLES-$(call ALLYES, ASS_DEMUXER, MATROSKA_MUXER) += fate-binsub-mksenc +FATE_SUBTITLES-$(call ALLYES, ASS_DEMUXER MATROSKA_MUXER) += fate-binsub-mksenc fate-binsub-mksenc: CMD = md5pipe -i $(TARGET_SAMPLES)/sub/1ededcbd7b.ass -c copy -f matroska -flags +bitexact -fflags +bitexact FATE_SUBTITLES_ASS-$(call DEMDEC, JACOSUB, JACOSUB) += fate-sub-jacosub diff --git a/tests/fate/vcodec.mak b/tests/fate/vcodec.mak index ef892366eb..2e6d16f1e7 100644 --- a/tests/fate/vcodec.mak +++ b/tests/fate/vcodec.mak @@ -4,8 +4,8 @@ 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 0 $(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 0 $(DECOPTS)" "" "$(DECINOPTS)" +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%: CMP_UNIT = 1 fate-vsynth%: REF = $(SRC_PATH)/tests/ref/vsynth/$(@:fate-%=%) diff --git a/tests/ref/fate/adpcm-ima-smjpeg b/tests/ref/fate/adpcm-ima-smjpeg index d56014ea01..a216e3ab5e 100644 --- a/tests/ref/fate/adpcm-ima-smjpeg +++ b/tests/ref/fate/adpcm-ima-smjpeg @@ -9,348 +9,348 @@ 0, 1024, 1024, 512, 1024, 0xed2d3f6b 0, 1533, 1533, 512, 1024, 0x51f6ccb3 0, 2040, 2040, 512, 1024, 0x58bd75aa -0, 2552, 2552, 512, 1024, 0xd857a310 -0, 3064, 3064, 512, 1024, 0xc483a5b8 -0, 3576, 3576, 512, 1024, 0x923ecf67 -0, 4088, 4088, 512, 1024, 0xf87dcd53 +0, 2558, 2558, 512, 1024, 0xd857a310 +0, 3070, 3070, 512, 1024, 0xc483a5b8 +0, 3582, 3582, 512, 1024, 0x923ecf67 +0, 4091, 4091, 512, 1024, 0xf87dcd53 0, 4598, 4598, 512, 1024, 0xdc32c002 -0, 5110, 5110, 512, 1024, 0xb760def1 -0, 5622, 5622, 512, 1024, 0x6838d2b2 -0, 6134, 6134, 512, 1024, 0xe45aca1e -0, 6646, 6646, 512, 1024, 0xde1fb955 -0, 7158, 7158, 512, 1024, 0x9e23b949 -0, 7670, 7670, 512, 1024, 0x840cc000 -0, 8182, 8182, 512, 1024, 0x0a29cbfa -0, 8694, 8694, 512, 1024, 0x9871d4c4 +0, 5116, 5116, 512, 1024, 0xb760def1 +0, 5628, 5628, 512, 1024, 0x6838d2b2 +0, 6140, 6140, 512, 1024, 0xe45aca1e +0, 6649, 6649, 512, 1024, 0xde1fb955 +0, 7166, 7166, 512, 1024, 0x9e23b949 +0, 7678, 7678, 512, 1024, 0x840cc000 +0, 8190, 8190, 512, 1024, 0x0a29cbfa +0, 8699, 8699, 512, 1024, 0x9871d4c4 0, 9206, 9206, 512, 1024, 0xb35dc9f2 -0, 9718, 9718, 512, 1024, 0xf37fda0a -0, 10230, 10230, 512, 1024, 0xa640f990 -0, 10742, 10742, 512, 1024, 0x516fe6f5 -0, 11254, 11254, 512, 1024, 0xc78bc6a6 -0, 11766, 11766, 512, 1024, 0x700fd6ee -0, 12278, 12278, 512, 1024, 0x5383d5ad -0, 12790, 12790, 512, 1024, 0xbe01d091 -0, 13302, 13302, 512, 1024, 0x72dfcfc7 -0, 13814, 13814, 512, 1024, 0xd8fecea9 -0, 14326, 14326, 512, 1024, 0xa464d79b -0, 14838, 14838, 512, 1024, 0xf394e2cb -0, 15350, 15350, 512, 1024, 0xa301ec49 -0, 15862, 15862, 512, 1024, 0x5e09d60f -0, 16374, 16374, 512, 1024, 0xd13edd6f -0, 16886, 16886, 512, 1024, 0x7423ef39 -0, 17398, 17398, 512, 1024, 0x96e2f083 -0, 17910, 17910, 512, 1024, 0x5ed7dbee -0, 18422, 18422, 512, 1024, 0x3874f714 -0, 18934, 18934, 512, 1024, 0xa5e6edab -0, 19446, 19446, 512, 1024, 0x0a04ee3a -0, 19958, 19958, 512, 1024, 0xadfee6b9 -0, 20470, 20470, 512, 1024, 0xd0bbe6d2 -0, 20982, 20982, 512, 1024, 0x223eebb7 -0, 21494, 21494, 512, 1024, 0x0473e479 -0, 22006, 22006, 512, 1024, 0xdf15e51e -0, 22518, 22518, 512, 1024, 0xa954e483 -0, 23030, 23030, 512, 1024, 0x6df3ed03 -0, 23542, 23542, 512, 1024, 0x0860e544 -0, 24054, 24054, 512, 1024, 0xc241e8dc -0, 24566, 24566, 512, 1024, 0xd0e1d6a4 -0, 25078, 25078, 512, 1024, 0xcb2ff988 +0, 9724, 9724, 512, 1024, 0xf37fda0a +0, 10236, 10236, 512, 1024, 0xa640f990 +0, 10748, 10748, 512, 1024, 0x516fe6f5 +0, 11257, 11257, 512, 1024, 0xc78bc6a6 +0, 11775, 11775, 512, 1024, 0x700fd6ee +0, 12287, 12287, 512, 1024, 0x5383d5ad +0, 12799, 12799, 512, 1024, 0xbe01d091 +0, 13308, 13308, 512, 1024, 0x72dfcfc7 +0, 13815, 13815, 512, 1024, 0xd8fecea9 +0, 14333, 14333, 512, 1024, 0xa464d79b +0, 14845, 14845, 512, 1024, 0xf394e2cb +0, 15357, 15357, 512, 1024, 0xa301ec49 +0, 15865, 15865, 512, 1024, 0x5e09d60f +0, 16383, 16383, 512, 1024, 0xd13edd6f +0, 16895, 16895, 512, 1024, 0x7423ef39 +0, 17407, 17407, 512, 1024, 0x96e2f083 +0, 17916, 17916, 512, 1024, 0x5ed7dbee +0, 18423, 18423, 512, 1024, 0x3874f714 +0, 18941, 18941, 512, 1024, 0xa5e6edab +0, 19453, 19453, 512, 1024, 0x0a04ee3a +0, 19965, 19965, 512, 1024, 0xadfee6b9 +0, 20474, 20474, 512, 1024, 0xd0bbe6d2 +0, 20992, 20992, 512, 1024, 0x223eebb7 +0, 21504, 21504, 512, 1024, 0x0473e479 +0, 22016, 22016, 512, 1024, 0xdf15e51e +0, 22525, 22525, 512, 1024, 0xa954e483 +0, 23032, 23032, 512, 1024, 0x6df3ed03 +0, 23549, 23549, 512, 1024, 0x0860e544 +0, 24061, 24061, 512, 1024, 0xc241e8dc +0, 24573, 24573, 512, 1024, 0xd0e1d6a4 +0, 25082, 25082, 512, 1024, 0xcb2ff988 0, 25590, 25590, 512, 1024, 0x51fae08e -0, 26102, 26102, 512, 1024, 0xae39f2fc -0, 26614, 26614, 512, 1024, 0xfd74f07c -0, 27126, 27126, 512, 1024, 0x1936edc1 -0, 27638, 27638, 512, 1024, 0x95f8deae -0, 28150, 28150, 512, 1024, 0x93bdf605 -0, 28662, 28662, 512, 1024, 0x7a07dd32 -0, 29174, 29174, 512, 1024, 0x6889fdc1 -0, 29686, 29686, 512, 1024, 0x989bf024 +0, 26107, 26107, 512, 1024, 0xae39f2fc +0, 26619, 26619, 512, 1024, 0xfd74f07c +0, 27131, 27131, 512, 1024, 0x1936edc1 +0, 27640, 27640, 512, 1024, 0x95f8deae +0, 28158, 28158, 512, 1024, 0x93bdf605 +0, 28670, 28670, 512, 1024, 0x7a07dd32 +0, 29182, 29182, 512, 1024, 0x6889fdc1 +0, 29691, 29691, 512, 1024, 0x989bf024 0, 30198, 30198, 512, 1024, 0xc764ce80 -0, 30710, 30710, 512, 1024, 0x0e62d721 -0, 31222, 31222, 512, 1024, 0x59c2fbe3 -0, 31734, 31734, 512, 1024, 0xf14ee29d -0, 32246, 32246, 512, 1024, 0x02a0f21b -0, 32758, 32758, 512, 1024, 0xadb3d361 -0, 33270, 33270, 512, 1024, 0xdcb3d1fc -0, 33782, 33782, 512, 1024, 0x2924f9dc -0, 34294, 34294, 512, 1024, 0x7507ebec +0, 30716, 30716, 512, 1024, 0x0e62d721 +0, 31228, 31228, 512, 1024, 0x59c2fbe3 +0, 31740, 31740, 512, 1024, 0xf14ee29d +0, 32249, 32249, 512, 1024, 0x02a0f21b +0, 32766, 32766, 512, 1024, 0xadb3d361 +0, 33278, 33278, 512, 1024, 0xdcb3d1fc +0, 33790, 33790, 512, 1024, 0x2924f9dc +0, 34299, 34299, 512, 1024, 0x7507ebec 0, 34806, 34806, 512, 1024, 0xe009f343 -0, 35318, 35318, 512, 1024, 0x21e9e7ac -0, 35830, 35830, 512, 1024, 0x845bda9e -0, 36342, 36342, 512, 1024, 0xb1b3e632 -0, 36854, 36854, 512, 1024, 0x61ccf593 -0, 37366, 37366, 512, 1024, 0x8cdbf603 -0, 37878, 37878, 512, 1024, 0xf8f7e673 -0, 38390, 38390, 512, 1024, 0x55efdd24 -0, 38902, 38902, 512, 1024, 0x4059e8ff -0, 39414, 39414, 512, 1024, 0xb3afe5be -0, 39926, 39926, 512, 1024, 0x7236e965 -0, 40438, 40438, 512, 1024, 0xe683db69 -0, 40950, 40950, 512, 1024, 0x29e3d93c -0, 41462, 41462, 512, 1024, 0x74f2f27f -0, 41974, 41974, 512, 1024, 0x32cde3ba -0, 42486, 42486, 512, 1024, 0xe907f171 -0, 42998, 42998, 512, 1024, 0x206ae2a5 -0, 43510, 43510, 512, 1024, 0x6379efa1 -0, 44022, 44022, 512, 1024, 0x0f0fee85 -0, 44534, 44534, 512, 1024, 0x3195e314 -0, 45046, 45046, 512, 1024, 0x4646ead3 -0, 45558, 45558, 512, 1024, 0x5635dcf5 -0, 46070, 46070, 512, 1024, 0xd76fc780 -0, 46582, 46582, 512, 1024, 0x847ff8a5 -0, 47094, 47094, 512, 1024, 0xaca8eda3 -0, 47606, 47606, 512, 1024, 0x9a2de1ea -0, 48118, 48118, 512, 1024, 0xc92ff23a -0, 48630, 48630, 512, 1024, 0x0e0ef038 -0, 49142, 49142, 512, 1024, 0xc32cf495 -0, 49654, 49654, 512, 1024, 0x6ab1ec79 -0, 50166, 50166, 512, 1024, 0xe43cd8d6 -0, 50678, 50678, 512, 1024, 0x4ba2deab +0, 35324, 35324, 512, 1024, 0x21e9e7ac +0, 35836, 35836, 512, 1024, 0x845bda9e +0, 36348, 36348, 512, 1024, 0xb1b3e632 +0, 36857, 36857, 512, 1024, 0x61ccf593 +0, 37375, 37375, 512, 1024, 0x8cdbf603 +0, 37887, 37887, 512, 1024, 0xf8f7e673 +0, 38399, 38399, 512, 1024, 0x55efdd24 +0, 38908, 38908, 512, 1024, 0x4059e8ff +0, 39415, 39415, 512, 1024, 0xb3afe5be +0, 39933, 39933, 512, 1024, 0x7236e965 +0, 40445, 40445, 512, 1024, 0xe683db69 +0, 40957, 40957, 512, 1024, 0x29e3d93c +0, 41466, 41466, 512, 1024, 0x74f2f27f +0, 41983, 41983, 512, 1024, 0x32cde3ba +0, 42495, 42495, 512, 1024, 0xe907f171 +0, 43007, 43007, 512, 1024, 0x206ae2a5 +0, 43516, 43516, 512, 1024, 0x6379efa1 +0, 44023, 44023, 512, 1024, 0x0f0fee85 +0, 44541, 44541, 512, 1024, 0x3195e314 +0, 45053, 45053, 512, 1024, 0x4646ead3 +0, 45565, 45565, 512, 1024, 0x5635dcf5 +0, 46074, 46074, 512, 1024, 0xd76fc780 +0, 46592, 46592, 512, 1024, 0x847ff8a5 +0, 47104, 47104, 512, 1024, 0xaca8eda3 +0, 47616, 47616, 512, 1024, 0x9a2de1ea +0, 48125, 48125, 512, 1024, 0xc92ff23a +0, 48632, 48632, 512, 1024, 0x0e0ef038 +0, 49149, 49149, 512, 1024, 0xc32cf495 +0, 49661, 49661, 512, 1024, 0x6ab1ec79 +0, 50173, 50173, 512, 1024, 0xe43cd8d6 +0, 50682, 50682, 512, 1024, 0x4ba2deab 0, 51190, 51190, 512, 1024, 0x6d16ea0e -0, 51702, 51702, 512, 1024, 0xe5b0ee70 -0, 52214, 52214, 512, 1024, 0xcf6cf074 -0, 52726, 52726, 512, 1024, 0x2206e61d -0, 53238, 53238, 512, 1024, 0xfbb9e7e7 -0, 53750, 53750, 512, 1024, 0x2bc1e115 -0, 54262, 54262, 512, 1024, 0x4ca6e5c5 -0, 54774, 54774, 512, 1024, 0x061cead0 -0, 55286, 55286, 512, 1024, 0x3dc9f950 +0, 51707, 51707, 512, 1024, 0xe5b0ee70 +0, 52219, 52219, 512, 1024, 0xcf6cf074 +0, 52731, 52731, 512, 1024, 0x2206e61d +0, 53240, 53240, 512, 1024, 0xfbb9e7e7 +0, 53758, 53758, 512, 1024, 0x2bc1e115 +0, 54270, 54270, 512, 1024, 0x4ca6e5c5 +0, 54782, 54782, 512, 1024, 0x061cead0 +0, 55291, 55291, 512, 1024, 0x3dc9f950 0, 55798, 55798, 512, 1024, 0x9399f10d -0, 56310, 56310, 512, 1024, 0xa2bff5ae -0, 56822, 56822, 512, 1024, 0xd21de569 -0, 57334, 57334, 512, 1024, 0x1c45e3be -0, 57846, 57846, 512, 1024, 0xff5dff1c -0, 58358, 58358, 512, 1024, 0x992df5d3 -0, 58870, 58870, 512, 1024, 0xafedea2f -0, 59382, 59382, 512, 1024, 0x6e73d6a8 -0, 59894, 59894, 512, 1024, 0x72dff283 +0, 56316, 56316, 512, 1024, 0xa2bff5ae +0, 56828, 56828, 512, 1024, 0xd21de569 +0, 57340, 57340, 512, 1024, 0x1c45e3be +0, 57849, 57849, 512, 1024, 0xff5dff1c +0, 58366, 58366, 512, 1024, 0x992df5d3 +0, 58878, 58878, 512, 1024, 0xafedea2f +0, 59390, 59390, 512, 1024, 0x6e73d6a8 +0, 59899, 59899, 512, 1024, 0x72dff283 0, 60406, 60406, 512, 1024, 0x50b5f1a6 -0, 60918, 60918, 512, 1024, 0xffe1decb -0, 61430, 61430, 512, 1024, 0x8993ecff -0, 61942, 61942, 512, 1024, 0x954bd63a -0, 62454, 62454, 512, 1024, 0x4707f577 -0, 62966, 62966, 512, 1024, 0x7a88f81f -0, 63478, 63478, 512, 1024, 0xc771f537 -0, 63990, 63990, 512, 1024, 0x7aade6af -0, 64502, 64502, 512, 1024, 0x8af5ede5 -0, 65014, 65014, 512, 1024, 0x7500f3f1 -0, 65526, 65526, 512, 1024, 0xea36f707 -0, 66038, 66038, 512, 1024, 0x1a26e39a -0, 66550, 66550, 512, 1024, 0xa04cf00d -0, 67062, 67062, 512, 1024, 0xc362f182 -0, 67574, 67574, 512, 1024, 0x79c8f82c -0, 68086, 68086, 512, 1024, 0x6480eee1 -0, 68598, 68598, 512, 1024, 0x7152eaa0 -0, 69110, 69110, 512, 1024, 0x5dfee6a9 -0, 69622, 69622, 512, 1024, 0x0afae660 -0, 70134, 70134, 512, 1024, 0xdc98e9fc -0, 70646, 70646, 512, 1024, 0x10b7da06 -0, 71158, 71158, 512, 1024, 0x0571e585 -0, 71670, 71670, 512, 1024, 0x18ddf45e -0, 72182, 72182, 512, 1024, 0x2cbef242 -0, 72694, 72694, 512, 1024, 0xf5380845 -0, 73206, 73206, 512, 1024, 0x34fff45e -0, 73718, 73718, 512, 1024, 0x6f97e490 -0, 74230, 74230, 512, 1024, 0x77d6f0db -0, 74742, 74742, 512, 1024, 0xa25ce2db -0, 75254, 75254, 512, 1024, 0x8260e4e9 -0, 75766, 75766, 512, 1024, 0xc3b2f7d2 -0, 76278, 76278, 512, 1024, 0x82a7edae +0, 60924, 60924, 512, 1024, 0xffe1decb +0, 61436, 61436, 512, 1024, 0x8993ecff +0, 61948, 61948, 512, 1024, 0x954bd63a +0, 62457, 62457, 512, 1024, 0x4707f577 +0, 62975, 62975, 512, 1024, 0x7a88f81f +0, 63487, 63487, 512, 1024, 0xc771f537 +0, 63999, 63999, 512, 1024, 0x7aade6af +0, 64508, 64508, 512, 1024, 0x8af5ede5 +0, 65015, 65015, 512, 1024, 0x7500f3f1 +0, 65533, 65533, 512, 1024, 0xea36f707 +0, 66045, 66045, 512, 1024, 0x1a26e39a +0, 66557, 66557, 512, 1024, 0xa04cf00d +0, 67066, 67066, 512, 1024, 0xc362f182 +0, 67583, 67583, 512, 1024, 0x79c8f82c +0, 68095, 68095, 512, 1024, 0x6480eee1 +0, 68607, 68607, 512, 1024, 0x7152eaa0 +0, 69116, 69116, 512, 1024, 0x5dfee6a9 +0, 69623, 69623, 512, 1024, 0x0afae660 +0, 70141, 70141, 512, 1024, 0xdc98e9fc +0, 70653, 70653, 512, 1024, 0x10b7da06 +0, 71165, 71165, 512, 1024, 0x0571e585 +0, 71674, 71674, 512, 1024, 0x18ddf45e +0, 72192, 72192, 512, 1024, 0x2cbef242 +0, 72704, 72704, 512, 1024, 0xf5380845 +0, 73216, 73216, 512, 1024, 0x34fff45e +0, 73725, 73725, 512, 1024, 0x6f97e490 +0, 74232, 74232, 512, 1024, 0x77d6f0db +0, 74750, 74750, 512, 1024, 0xa25ce2db +0, 75262, 75262, 512, 1024, 0x8260e4e9 +0, 75774, 75774, 512, 1024, 0xc3b2f7d2 +0, 76282, 76282, 512, 1024, 0x82a7edae 0, 76790, 76790, 512, 1024, 0x7d08dd54 -0, 77302, 77302, 512, 1024, 0x9059eda6 -0, 77814, 77814, 512, 1024, 0xbebaec88 -0, 78326, 78326, 512, 1024, 0xd9afd586 -0, 78838, 78838, 512, 1024, 0x0ca3e622 -0, 79350, 79350, 512, 1024, 0x4123e9e6 -0, 79862, 79862, 512, 1024, 0x2ff9f95c -0, 80374, 80374, 512, 1024, 0x8522e261 -0, 80886, 80886, 512, 1024, 0xe4f8f499 +0, 77307, 77307, 512, 1024, 0x9059eda6 +0, 77819, 77819, 512, 1024, 0xbebaec88 +0, 78331, 78331, 512, 1024, 0xd9afd586 +0, 78840, 78840, 512, 1024, 0x0ca3e622 +0, 79358, 79358, 512, 1024, 0x4123e9e6 +0, 79870, 79870, 512, 1024, 0x2ff9f95c +0, 80382, 80382, 512, 1024, 0x8522e261 +0, 80891, 80891, 512, 1024, 0xe4f8f499 0, 81398, 81398, 512, 1024, 0x34f3f2bd -0, 81910, 81910, 512, 1024, 0x82efe863 -0, 82422, 82422, 512, 1024, 0x9966fcea -0, 82934, 82934, 512, 1024, 0xe94de3fd -0, 83446, 83446, 512, 1024, 0x1ce0e27b -0, 83958, 83958, 512, 1024, 0xd718dcde -0, 84470, 84470, 512, 1024, 0xd503e724 -0, 84982, 84982, 512, 1024, 0x427ee3b2 -0, 85494, 85494, 512, 1024, 0x4512dcc4 -0, 86006, 86006, 512, 1024, 0xcf31e77c -0, 86518, 86518, 512, 1024, 0xeb41ea81 -0, 87030, 87030, 512, 1024, 0xfa43e67c -0, 87542, 87542, 512, 1024, 0x8162f3c9 -0, 88054, 88054, 512, 1024, 0x1b55f6b0 -0, 88566, 88566, 512, 1024, 0x3ebeec44 -0, 89078, 89078, 512, 1024, 0x740fe0c4 -0, 89590, 89590, 512, 1024, 0x8fb4e8b2 -0, 90102, 90102, 512, 1024, 0xe49de6a2 -0, 90614, 90614, 512, 1024, 0xd64febdf -0, 91126, 91126, 512, 1024, 0x0e74ee08 -0, 91638, 91638, 512, 1024, 0x6c0ddf07 -0, 92150, 92150, 512, 1024, 0x7fb8e3c9 -0, 92662, 92662, 512, 1024, 0x52bfe96c -0, 93174, 93174, 512, 1024, 0xfc22ee64 -0, 93686, 93686, 512, 1024, 0xe20ae718 -0, 94198, 94198, 512, 1024, 0xa94be395 -0, 94710, 94710, 512, 1024, 0xded306d0 -0, 95222, 95222, 512, 1024, 0x31f7c831 -0, 95734, 95734, 512, 1024, 0x0ffde0a8 -0, 96246, 96246, 512, 1024, 0xc692e3e0 -0, 96758, 96758, 512, 1024, 0x1d8ff7c7 -0, 97270, 97270, 512, 1024, 0x038ee172 -0, 97782, 97782, 512, 1024, 0x9a1eef59 -0, 98294, 98294, 512, 1024, 0x158fe750 -0, 98806, 98806, 512, 1024, 0xac15e42c -0, 99318, 99318, 512, 1024, 0x6323ed44 -0, 99830, 99830, 512, 1024, 0xd10ce4bb -0, 100342, 100342, 512, 1024, 0xc1cce296 -0, 100854, 100854, 512, 1024, 0x0782f094 -0, 101366, 101366, 512, 1024, 0xd109de36 -0, 101878, 101878, 512, 1024, 0x175600fb +0, 81916, 81916, 512, 1024, 0x82efe863 +0, 82428, 82428, 512, 1024, 0x9966fcea +0, 82940, 82940, 512, 1024, 0xe94de3fd +0, 83449, 83449, 512, 1024, 0x1ce0e27b +0, 83966, 83966, 512, 1024, 0xd718dcde +0, 84478, 84478, 512, 1024, 0xd503e724 +0, 84990, 84990, 512, 1024, 0x427ee3b2 +0, 85499, 85499, 512, 1024, 0x4512dcc4 +0, 86007, 86007, 512, 1024, 0xcf31e77c +0, 86524, 86524, 512, 1024, 0xeb41ea81 +0, 87036, 87036, 512, 1024, 0xfa43e67c +0, 87548, 87548, 512, 1024, 0x8162f3c9 +0, 88057, 88057, 512, 1024, 0x1b55f6b0 +0, 88575, 88575, 512, 1024, 0x3ebeec44 +0, 89087, 89087, 512, 1024, 0x740fe0c4 +0, 89599, 89599, 512, 1024, 0x8fb4e8b2 +0, 90108, 90108, 512, 1024, 0xe49de6a2 +0, 90615, 90615, 512, 1024, 0xd64febdf +0, 91133, 91133, 512, 1024, 0x0e74ee08 +0, 91645, 91645, 512, 1024, 0x6c0ddf07 +0, 92157, 92157, 512, 1024, 0x7fb8e3c9 +0, 92666, 92666, 512, 1024, 0x52bfe96c +0, 93183, 93183, 512, 1024, 0xfc22ee64 +0, 93695, 93695, 512, 1024, 0xe20ae718 +0, 94207, 94207, 512, 1024, 0xa94be395 +0, 94716, 94716, 512, 1024, 0xded306d0 +0, 95223, 95223, 512, 1024, 0x31f7c831 +0, 95741, 95741, 512, 1024, 0x0ffde0a8 +0, 96253, 96253, 512, 1024, 0xc692e3e0 +0, 96765, 96765, 512, 1024, 0x1d8ff7c7 +0, 97274, 97274, 512, 1024, 0x038ee172 +0, 97792, 97792, 512, 1024, 0x9a1eef59 +0, 98304, 98304, 512, 1024, 0x158fe750 +0, 98816, 98816, 512, 1024, 0xac15e42c +0, 99325, 99325, 512, 1024, 0x6323ed44 +0, 99832, 99832, 512, 1024, 0xd10ce4bb +0, 100350, 100350, 512, 1024, 0xc1cce296 +0, 100862, 100862, 512, 1024, 0x0782f094 +0, 101374, 101374, 512, 1024, 0xd109de36 +0, 101883, 101883, 512, 1024, 0x175600fb 0, 102390, 102390, 512, 1024, 0x95d5e8d9 -0, 102902, 102902, 512, 1024, 0xebb6eee1 -0, 103414, 103414, 512, 1024, 0x187cfadc -0, 103926, 103926, 512, 1024, 0xce35fa5c -0, 104438, 104438, 512, 1024, 0x8327eea2 -0, 104950, 104950, 512, 1024, 0x5543f219 -0, 105462, 105462, 512, 1024, 0xaacbe0dc -0, 105974, 105974, 512, 1024, 0xa538e9fb -0, 106486, 106486, 512, 1024, 0x4dcbe655 +0, 102907, 102907, 512, 1024, 0xebb6eee1 +0, 103419, 103419, 512, 1024, 0x187cfadc +0, 103931, 103931, 512, 1024, 0xce35fa5c +0, 104440, 104440, 512, 1024, 0x8327eea2 +0, 104958, 104958, 512, 1024, 0x5543f219 +0, 105470, 105470, 512, 1024, 0xaacbe0dc +0, 105982, 105982, 512, 1024, 0xa538e9fb +0, 106491, 106491, 512, 1024, 0x4dcbe655 0, 106998, 106998, 512, 1024, 0x86b6d93b -0, 107510, 107510, 512, 1024, 0x1a06f878 -0, 108022, 108022, 512, 1024, 0xd926e8ef -0, 108534, 108534, 512, 1024, 0xc624db2f -0, 109046, 109046, 512, 1024, 0x2153e20d -0, 109558, 109558, 512, 1024, 0x01dce868 -0, 110070, 110070, 512, 1024, 0xfa5fd3cd -0, 110582, 110582, 512, 1024, 0x2adef2d5 -0, 111094, 111094, 512, 1024, 0x4f48f8e2 -0, 111606, 111606, 512, 1024, 0x613feeee -0, 112118, 112118, 512, 1024, 0x3780de8a -0, 112630, 112630, 512, 1024, 0x2093eb65 -0, 113142, 113142, 512, 1024, 0x54baebbb -0, 113654, 113654, 512, 1024, 0x8686dd7c -0, 114166, 114166, 512, 1024, 0x7f8ae80c -0, 114678, 114678, 512, 1024, 0x7aede972 -0, 115190, 115190, 512, 1024, 0x971bebc0 -0, 115702, 115702, 512, 1024, 0x2dd5fd4b -0, 116214, 116214, 512, 1024, 0xb1b3e4a3 -0, 116726, 116726, 512, 1024, 0x192defc6 -0, 117238, 117238, 512, 1024, 0x5e46ec44 -0, 117750, 117750, 512, 1024, 0xe6d8e05a -0, 118262, 118262, 512, 1024, 0x7e2fe2b0 -0, 118774, 118774, 512, 1024, 0x9e3bdf80 -0, 119286, 119286, 512, 1024, 0xa98cd85e -0, 119798, 119798, 512, 1024, 0x6061e0c4 -0, 120310, 120310, 512, 1024, 0x6112f3fc -0, 120822, 120822, 512, 1024, 0x99bdfb01 -0, 121334, 121334, 512, 1024, 0x3f5df3ca -0, 121846, 121846, 512, 1024, 0xf5ebeb05 -0, 122358, 122358, 512, 1024, 0x8498e565 -0, 122870, 122870, 512, 1024, 0x0497f0b7 -0, 123382, 123382, 512, 1024, 0x626ae800 -0, 123894, 123894, 512, 1024, 0xfb71eec4 -0, 124406, 124406, 512, 1024, 0xa86ee739 -0, 124918, 124918, 512, 1024, 0x25c0e050 -0, 125430, 125430, 512, 1024, 0x6027e91e -0, 125942, 125942, 512, 1024, 0x6772df6e -0, 126454, 126454, 512, 1024, 0xfefff844 -0, 126966, 126966, 512, 1024, 0x547be862 -0, 127478, 127478, 512, 1024, 0xca84e795 +0, 107516, 107516, 512, 1024, 0x1a06f878 +0, 108028, 108028, 512, 1024, 0xd926e8ef +0, 108540, 108540, 512, 1024, 0xc624db2f +0, 109049, 109049, 512, 1024, 0x2153e20d +0, 109566, 109566, 512, 1024, 0x01dce868 +0, 110078, 110078, 512, 1024, 0xfa5fd3cd +0, 110590, 110590, 512, 1024, 0x2adef2d5 +0, 111099, 111099, 512, 1024, 0x4f48f8e2 +0, 111607, 111607, 512, 1024, 0x613feeee +0, 112124, 112124, 512, 1024, 0x3780de8a +0, 112636, 112636, 512, 1024, 0x2093eb65 +0, 113148, 113148, 512, 1024, 0x54baebbb +0, 113657, 113657, 512, 1024, 0x8686dd7c +0, 114175, 114175, 512, 1024, 0x7f8ae80c +0, 114687, 114687, 512, 1024, 0x7aede972 +0, 115199, 115199, 512, 1024, 0x971bebc0 +0, 115708, 115708, 512, 1024, 0x2dd5fd4b +0, 116215, 116215, 512, 1024, 0xb1b3e4a3 +0, 116733, 116733, 512, 1024, 0x192defc6 +0, 117245, 117245, 512, 1024, 0x5e46ec44 +0, 117757, 117757, 512, 1024, 0xe6d8e05a +0, 118266, 118266, 512, 1024, 0x7e2fe2b0 +0, 118783, 118783, 512, 1024, 0x9e3bdf80 +0, 119295, 119295, 512, 1024, 0xa98cd85e +0, 119807, 119807, 512, 1024, 0x6061e0c4 +0, 120316, 120316, 512, 1024, 0x6112f3fc +0, 120823, 120823, 512, 1024, 0x99bdfb01 +0, 121341, 121341, 512, 1024, 0x3f5df3ca +0, 121853, 121853, 512, 1024, 0xf5ebeb05 +0, 122365, 122365, 512, 1024, 0x8498e565 +0, 122874, 122874, 512, 1024, 0x0497f0b7 +0, 123392, 123392, 512, 1024, 0x626ae800 +0, 123904, 123904, 512, 1024, 0xfb71eec4 +0, 124416, 124416, 512, 1024, 0xa86ee739 +0, 124925, 124925, 512, 1024, 0x25c0e050 +0, 125432, 125432, 512, 1024, 0x6027e91e +0, 125950, 125950, 512, 1024, 0x6772df6e +0, 126462, 126462, 512, 1024, 0xfefff844 +0, 126974, 126974, 512, 1024, 0x547be862 +0, 127483, 127483, 512, 1024, 0xca84e795 0, 127990, 127990, 512, 1024, 0xd124db3e -0, 128502, 128502, 512, 1024, 0xcaf3deb5 -0, 129014, 129014, 512, 1024, 0x487ce92d -0, 129526, 129526, 512, 1024, 0x117feb95 -0, 130038, 130038, 512, 1024, 0x7b63de3d -0, 130550, 130550, 512, 1024, 0xa529d8e1 -0, 131062, 131062, 512, 1024, 0x56f6da26 -0, 131574, 131574, 512, 1024, 0xffb8d5af -0, 132086, 132086, 512, 1024, 0xeecbdc04 +0, 128507, 128507, 512, 1024, 0xcaf3deb5 +0, 129019, 129019, 512, 1024, 0x487ce92d +0, 129531, 129531, 512, 1024, 0x117feb95 +0, 130040, 130040, 512, 1024, 0x7b63de3d +0, 130558, 130558, 512, 1024, 0xa529d8e1 +0, 131070, 131070, 512, 1024, 0x56f6da26 +0, 131582, 131582, 512, 1024, 0xffb8d5af +0, 132091, 132091, 512, 1024, 0xeecbdc04 0, 132598, 132598, 512, 1024, 0xfc59d2d2 -0, 133110, 133110, 512, 1024, 0xaf7acef7 -0, 133622, 133622, 512, 1024, 0x3f9bf258 -0, 134134, 134134, 512, 1024, 0xcf54e9d6 -0, 134646, 134646, 512, 1024, 0x680cd0aa -0, 135158, 135158, 512, 1024, 0x3c1bdc1f -0, 135670, 135670, 512, 1024, 0x8c8ffe22 -0, 136182, 136182, 512, 1024, 0xf415d362 -0, 136694, 136694, 512, 1024, 0x8c8cdaa9 -0, 137206, 137206, 512, 1024, 0x9531e9f1 -0, 137718, 137718, 512, 1024, 0x223ce536 -0, 138230, 138230, 512, 1024, 0xdfbce5f9 -0, 138742, 138742, 512, 1024, 0x20b6ed7d -0, 139254, 139254, 512, 1024, 0x1a17e109 -0, 139766, 139766, 512, 1024, 0xc672eaea -0, 140278, 140278, 512, 1024, 0x12a7dc5e -0, 140790, 140790, 512, 1024, 0x4497f342 -0, 141302, 141302, 512, 1024, 0xdfb5db4b -0, 141814, 141814, 512, 1024, 0xde48ef6c -0, 142326, 142326, 512, 1024, 0x1d98e316 -0, 142838, 142838, 512, 1024, 0xbd2ad72f -0, 143350, 143350, 512, 1024, 0xf1aad776 -0, 143862, 143862, 512, 1024, 0x4db3e3c0 -0, 144374, 144374, 512, 1024, 0x832de0a0 -0, 144886, 144886, 512, 1024, 0xc5f0ef25 -0, 145398, 145398, 512, 1024, 0x419bda6e -0, 145910, 145910, 512, 1024, 0x5de7f77e -0, 146422, 146422, 512, 1024, 0x0063ec9a -0, 146934, 146934, 512, 1024, 0x10c3d470 -0, 147446, 147446, 512, 1024, 0xba66d226 -0, 147958, 147958, 512, 1024, 0xea47ded3 -0, 148470, 148470, 512, 1024, 0x6202d67b -0, 148982, 148982, 512, 1024, 0x3f80e7cf -0, 149494, 149494, 512, 1024, 0x4e64eaae -0, 150006, 150006, 512, 1024, 0x2108e83d -0, 150518, 150518, 512, 1024, 0x38c3dec1 -0, 151030, 151030, 512, 1024, 0x46d3f77a -0, 151542, 151542, 512, 1024, 0x4838e787 -0, 152054, 152054, 512, 1024, 0xc71df16d -0, 152566, 152566, 512, 1024, 0xdbe4ebbd -0, 153078, 153078, 512, 1024, 0xa156d07b +0, 133116, 133116, 512, 1024, 0xaf7acef7 +0, 133628, 133628, 512, 1024, 0x3f9bf258 +0, 134140, 134140, 512, 1024, 0xcf54e9d6 +0, 134649, 134649, 512, 1024, 0x680cd0aa +0, 135167, 135167, 512, 1024, 0x3c1bdc1f +0, 135679, 135679, 512, 1024, 0x8c8ffe22 +0, 136191, 136191, 512, 1024, 0xf415d362 +0, 136699, 136699, 512, 1024, 0x8c8cdaa9 +0, 137207, 137207, 512, 1024, 0x9531e9f1 +0, 137724, 137724, 512, 1024, 0x223ce536 +0, 138236, 138236, 512, 1024, 0xdfbce5f9 +0, 138748, 138748, 512, 1024, 0x20b6ed7d +0, 139257, 139257, 512, 1024, 0x1a17e109 +0, 139775, 139775, 512, 1024, 0xc672eaea +0, 140287, 140287, 512, 1024, 0x12a7dc5e +0, 140799, 140799, 512, 1024, 0x4497f342 +0, 141308, 141308, 512, 1024, 0xdfb5db4b +0, 141815, 141815, 512, 1024, 0xde48ef6c +0, 142333, 142333, 512, 1024, 0x1d98e316 +0, 142845, 142845, 512, 1024, 0xbd2ad72f +0, 143357, 143357, 512, 1024, 0xf1aad776 +0, 143866, 143866, 512, 1024, 0x4db3e3c0 +0, 144383, 144383, 512, 1024, 0x832de0a0 +0, 144895, 144895, 512, 1024, 0xc5f0ef25 +0, 145407, 145407, 512, 1024, 0x419bda6e +0, 145916, 145916, 512, 1024, 0x5de7f77e +0, 146424, 146424, 512, 1024, 0x0063ec9a +0, 146941, 146941, 512, 1024, 0x10c3d470 +0, 147453, 147453, 512, 1024, 0xba66d226 +0, 147965, 147965, 512, 1024, 0xea47ded3 +0, 148474, 148474, 512, 1024, 0x6202d67b +0, 148992, 148992, 512, 1024, 0x3f80e7cf +0, 149504, 149504, 512, 1024, 0x4e64eaae +0, 150016, 150016, 512, 1024, 0x2108e83d +0, 150525, 150525, 512, 1024, 0x38c3dec1 +0, 151032, 151032, 512, 1024, 0x46d3f77a +0, 151550, 151550, 512, 1024, 0x4838e787 +0, 152062, 152062, 512, 1024, 0xc71df16d +0, 152574, 152574, 512, 1024, 0xdbe4ebbd +0, 153083, 153083, 512, 1024, 0xa156d07b 0, 153590, 153590, 512, 1024, 0x34eddc80 -0, 154102, 154102, 512, 1024, 0xe840e87c -0, 154614, 154614, 512, 1024, 0x6accf8f5 -0, 155126, 155126, 512, 1024, 0xa1dbebb9 -0, 155638, 155638, 512, 1024, 0x6d07d98c -0, 156150, 156150, 512, 1024, 0x94c7e805 -0, 156662, 156662, 512, 1024, 0x5199e586 -0, 157174, 157174, 512, 1024, 0xe797e1aa -0, 157686, 157686, 512, 1024, 0xff19eda7 +0, 154107, 154107, 512, 1024, 0xe840e87c +0, 154619, 154619, 512, 1024, 0x6accf8f5 +0, 155131, 155131, 512, 1024, 0xa1dbebb9 +0, 155640, 155640, 512, 1024, 0x6d07d98c +0, 156158, 156158, 512, 1024, 0x94c7e805 +0, 156670, 156670, 512, 1024, 0x5199e586 +0, 157182, 157182, 512, 1024, 0xe797e1aa +0, 157691, 157691, 512, 1024, 0xff19eda7 0, 158198, 158198, 512, 1024, 0x9cb9d040 -0, 158710, 158710, 512, 1024, 0xaeedd325 -0, 159222, 159222, 512, 1024, 0xf5ade306 -0, 159734, 159734, 512, 1024, 0x54a5e129 -0, 160246, 160246, 512, 1024, 0x6665ddeb -0, 160758, 160758, 512, 1024, 0x9d18e033 -0, 161270, 161270, 512, 1024, 0x7f23df74 -0, 161782, 161782, 512, 1024, 0x7c34f158 -0, 162294, 162294, 512, 1024, 0x47f6dae2 -0, 162806, 162806, 512, 1024, 0x5ffdd903 -0, 163318, 163318, 512, 1024, 0x8233d108 -0, 163830, 163830, 512, 1024, 0x45c6e20d -0, 164342, 164342, 512, 1024, 0xae11fa6e -0, 164854, 164854, 512, 1024, 0xa30defd2 -0, 165366, 165366, 512, 1024, 0xfc1ecccf -0, 165878, 165878, 512, 1024, 0x920edc94 -0, 166390, 166390, 512, 1024, 0xd7f3dc58 -0, 166902, 166902, 512, 1024, 0x4972d37d -0, 167414, 167414, 512, 1024, 0xfefef358 -0, 167926, 167926, 512, 1024, 0x3648e473 -0, 168438, 168438, 512, 1024, 0x58dee6c3 -0, 168950, 168950, 512, 1024, 0x9cc6df27 -0, 169462, 169462, 512, 1024, 0x6adfe99c -0, 169974, 169974, 512, 1024, 0x6a56e11f -0, 170486, 170486, 512, 1024, 0x4860edf1 -0, 170998, 170998, 512, 1024, 0x9132f10a -0, 171510, 171510, 512, 1024, 0x3e09d209 -0, 172022, 172022, 512, 1024, 0x4b6bf4d8 -0, 172534, 172534, 512, 1024, 0x0cd5e838 -0, 173046, 173046, 512, 1024, 0x080be078 -0, 173558, 173558, 512, 1024, 0xfdb0e31c -0, 174070, 174070, 512, 1024, 0xced5e7bd -0, 174582, 174582, 512, 1024, 0x65b3e435 -0, 175094, 175094, 512, 1024, 0x5b5bfe2e -0, 175606, 175606, 512, 1024, 0xa8bde3cb -0, 176118, 176118, 512, 1024, 0xfd0fdefa -0, 176630, 176630, 512, 1024, 0xbec4ef95 -0, 177142, 177142, 512, 1024, 0x683ad8dd -0, 177654, 177654, 512, 1024, 0x8eefeb77 -0, 178166, 178166, 512, 1024, 0x84fc5878 -0, 178678, 178678, 512, 1024, 0x9a0ded60 +0, 158716, 158716, 512, 1024, 0xaeedd325 +0, 159228, 159228, 512, 1024, 0xf5ade306 +0, 159740, 159740, 512, 1024, 0x54a5e129 +0, 160249, 160249, 512, 1024, 0x6665ddeb +0, 160767, 160767, 512, 1024, 0x9d18e033 +0, 161279, 161279, 512, 1024, 0x7f23df74 +0, 161791, 161791, 512, 1024, 0x7c34f158 +0, 162300, 162300, 512, 1024, 0x47f6dae2 +0, 162807, 162807, 512, 1024, 0x5ffdd903 +0, 163324, 163324, 512, 1024, 0x8233d108 +0, 163836, 163836, 512, 1024, 0x45c6e20d +0, 164348, 164348, 512, 1024, 0xae11fa6e +0, 164857, 164857, 512, 1024, 0xa30defd2 +0, 165375, 165375, 512, 1024, 0xfc1ecccf +0, 165887, 165887, 512, 1024, 0x920edc94 +0, 166399, 166399, 512, 1024, 0xd7f3dc58 +0, 166908, 166908, 512, 1024, 0x4972d37d +0, 167415, 167415, 512, 1024, 0xfefef358 +0, 167933, 167933, 512, 1024, 0x3648e473 +0, 168445, 168445, 512, 1024, 0x58dee6c3 +0, 168957, 168957, 512, 1024, 0x9cc6df27 +0, 169466, 169466, 512, 1024, 0x6adfe99c +0, 169983, 169983, 512, 1024, 0x6a56e11f +0, 170495, 170495, 512, 1024, 0x4860edf1 +0, 171007, 171007, 512, 1024, 0x9132f10a +0, 171516, 171516, 512, 1024, 0x3e09d209 +0, 172024, 172024, 512, 1024, 0x4b6bf4d8 +0, 172541, 172541, 512, 1024, 0x0cd5e838 +0, 173053, 173053, 512, 1024, 0x080be078 +0, 173565, 173565, 512, 1024, 0xfdb0e31c +0, 174074, 174074, 512, 1024, 0xced5e7bd +0, 174592, 174592, 512, 1024, 0x65b3e435 +0, 175104, 175104, 512, 1024, 0x5b5bfe2e +0, 175616, 175616, 512, 1024, 0xa8bde3cb +0, 176125, 176125, 512, 1024, 0xfd0fdefa +0, 176632, 176632, 512, 1024, 0xbec4ef95 +0, 177150, 177150, 512, 1024, 0x683ad8dd +0, 177662, 177662, 512, 1024, 0x8eefeb77 +0, 178174, 178174, 512, 1024, 0x84fc5878 +0, 178683, 178683, 512, 1024, 0x9a0ded60 diff --git a/tests/ref/fate/amrnb-remux b/tests/ref/fate/amrnb-remux new file mode 100644 index 0000000000..4a78c479f2 --- /dev/null +++ b/tests/ref/fate/amrnb-remux @@ -0,0 +1,58 @@ +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 0: 4 +#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 0000000000..c350fc0b61 --- /dev/null +++ b/tests/ref/fate/amrwb-remux @@ -0,0 +1,58 @@ +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 0: 4 +#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/cdgraphics b/tests/ref/fate/cdgraphics index f079bd4df0..9ffe129397 100644 --- a/tests/ref/fate/cdgraphics +++ b/tests/ref/fate/cdgraphics @@ -16,202 +16,202 @@ 0, 10, 10, 1, 259200, 0x6779f55d 0, 11, 11, 1, 259200, 0x6779f55d 0, 12, 12, 1, 259200, 0x6779f55d -0, 13, 13, 1, 259200, 0xf33cc0c4 -0, 14, 14, 1, 259200, 0xf33cc0c4 -0, 15, 15, 1, 259200, 0xf33cc0c4 -0, 16, 16, 1, 259200, 0x098280da -0, 17, 17, 1, 259200, 0x098280da -0, 18, 18, 1, 259200, 0x098280da -0, 19, 19, 1, 259200, 0x098280da -0, 20, 20, 1, 259200, 0x098280da -0, 21, 21, 1, 259200, 0x098280da -0, 22, 22, 1, 259200, 0x098280da -0, 23, 23, 1, 259200, 0x098280da -0, 24, 24, 1, 259200, 0x098280da -0, 25, 25, 1, 259200, 0x098280da -0, 26, 26, 1, 259200, 0x098280da -0, 27, 27, 1, 259200, 0x098280da -0, 28, 28, 1, 259200, 0x098280da -0, 29, 29, 1, 259200, 0x098280da -0, 30, 30, 1, 259200, 0x098280da -0, 31, 31, 1, 259200, 0x098280da -0, 32, 32, 1, 259200, 0xf33cc0c4 -0, 33, 33, 1, 259200, 0xa389d0b4 -0, 34, 34, 1, 259200, 0xecf1f094 -0, 35, 35, 1, 259200, 0xe7171c77 -0, 37, 37, 1, 259200, 0xf9d72c67 -0, 38, 38, 1, 259200, 0x7932583b -0, 40, 40, 1, 259200, 0x1c618c07 -0, 41, 41, 1, 259200, 0x7e88c1d1 -0, 43, 43, 1, 259200, 0x2c5df59d -0, 44, 44, 1, 259200, 0xa78f435e -0, 46, 46, 1, 259200, 0xb96e5948 -0, 47, 47, 1, 259200, 0x85c1653c -0, 49, 49, 1, 259200, 0xefdc930e -0, 50, 50, 1, 259200, 0xea24bee2 -0, 52, 52, 1, 259200, 0x8feef8a8 -0, 53, 53, 1, 259200, 0x8a7b02ad -0, 55, 55, 1, 259200, 0xe41b2689 -0, 56, 56, 1, 259200, 0x007d307f -0, 58, 58, 1, 259200, 0xb0c9802f -0, 59, 59, 1, 259200, 0xb50c941b -0, 61, 61, 1, 259200, 0xdf7dc7e7 -0, 62, 62, 1, 259200, 0xbaac01bc -0, 64, 64, 1, 259200, 0x1ef70db0 -0, 65, 65, 1, 259200, 0xeeab4b72 -0, 67, 67, 1, 259200, 0x0eaf7d40 -0, 68, 68, 1, 259200, 0xc7bec4f8 -0, 70, 70, 1, 259200, 0xa506caf2 -0, 71, 71, 1, 259200, 0x268808c3 -0, 73, 73, 1, 259200, 0xebd90ebd -0, 74, 74, 1, 259200, 0x8d792aa1 -0, 76, 76, 1, 259200, 0x960d3a91 -0, 77, 77, 1, 259200, 0xf0395e6d -0, 79, 79, 1, 259200, 0x3d0e8645 -0, 80, 80, 1, 259200, 0x88bc9a31 -0, 82, 82, 1, 259200, 0xda37c209 -0, 83, 83, 1, 259200, 0xafa6c803 -0, 85, 85, 1, 259200, 0xdc58f5d5 -0, 86, 86, 1, 259200, 0x1a5ffbcf -0, 88, 88, 1, 259200, 0xc8872bae -0, 89, 89, 1, 259200, 0xc5472dac -0, 91, 91, 1, 259200, 0xd54e5f7a -0, 92, 92, 1, 259200, 0xf4576574 -0, 94, 94, 1, 259200, 0xdefaad2c -0, 95, 95, 1, 259200, 0xca44c316 -0, 97, 97, 1, 259200, 0x8102d504 -0, 98, 98, 1, 259200, 0xe0c8fcdc -0, 100, 100, 1, 259200, 0x53c100e7 -0, 101, 101, 1, 259200, 0x8de628bf -0, 103, 103, 1, 259200, 0x86f92eb9 -0, 104, 104, 1, 259200, 0x13c66285 -0, 106, 106, 1, 259200, 0xe5766c7b -0, 107, 107, 1, 259200, 0x3ddb9453 -0, 109, 109, 1, 259200, 0x39559a4d -0, 110, 110, 1, 259200, 0x507da443 -0, 112, 112, 1, 259200, 0x3b8dedf9 -0, 113, 113, 1, 259200, 0x55c9fde9 -0, 115, 115, 1, 259200, 0x7c43ffe7 -0, 116, 116, 1, 259200, 0xdf2c31c4 -0, 118, 118, 1, 259200, 0x144735c0 -0, 119, 119, 1, 259200, 0x9a716b8a -0, 121, 121, 1, 259200, 0x5ab08174 -0, 122, 122, 1, 259200, 0x06dcb540 -0, 124, 124, 1, 259200, 0x0d09b93c -0, 125, 125, 1, 259200, 0x5abce70e -0, 127, 127, 1, 259200, 0x38a4ed08 -0, 128, 128, 1, 259200, 0x427b30d3 -0, 130, 130, 1, 259200, 0x7f8d34cf -0, 131, 131, 1, 259200, 0xf5613cc7 -0, 133, 133, 1, 259200, 0x5086748f -0, 134, 134, 1, 259200, 0x7da8788b -0, 136, 136, 1, 259200, 0x79c8946f -0, 137, 137, 1, 259200, 0x65d9bc47 -0, 139, 139, 1, 259200, 0x3f5a0012 -0, 140, 140, 1, 259200, 0x4d9713fe -0, 142, 142, 1, 259200, 0x917839d8 -0, 143, 143, 1, 259200, 0x92624dc4 -0, 145, 145, 1, 259200, 0x465c739e -0, 146, 146, 1, 259200, 0x21137f92 -0, 148, 148, 1, 259200, 0xd677a76a -0, 149, 149, 1, 259200, 0xe1efb35e -0, 151, 151, 1, 259200, 0xd2d6d73a -0, 152, 152, 1, 259200, 0x06a8f31e -0, 154, 154, 1, 259200, 0x8aaf1d03 -0, 155, 155, 1, 259200, 0x9e0a42dd -0, 157, 157, 1, 259200, 0x1f7268b7 -0, 158, 158, 1, 259200, 0x1a3c6cb3 -0, 160, 160, 1, 259200, 0x5607aa75 -0, 161, 161, 1, 259200, 0xa19ebc63 -0, 163, 163, 1, 259200, 0x9dbaf42b -0, 164, 164, 1, 259200, 0x2d06fe21 -0, 166, 166, 1, 259200, 0x960e2c02 -0, 167, 167, 1, 259200, 0x04f935f8 -0, 169, 169, 1, 259200, 0x488143ea -0, 170, 170, 1, 259200, 0xcb515bd2 -0, 172, 172, 1, 259200, 0xa27c85a8 -0, 173, 173, 1, 259200, 0x3bb38da0 -0, 175, 175, 1, 259200, 0x39d9b17c -0, 176, 176, 1, 259200, 0x3fbcbd70 -0, 178, 178, 1, 259200, 0xbc19e548 -0, 179, 179, 1, 259200, 0x29400735 -0, 181, 181, 1, 259200, 0x21612d0f -0, 182, 182, 1, 259200, 0x66943705 -0, 184, 184, 1, 259200, 0x9efa6ccf -0, 185, 185, 1, 259200, 0x3b4180bb -0, 187, 187, 1, 259200, 0x9a8aa695 -0, 188, 188, 1, 259200, 0x6529b883 -0, 190, 190, 1, 259200, 0x6e1aec4f -0, 191, 191, 1, 259200, 0x3ebc2426 -0, 193, 193, 1, 259200, 0xff6e3a10 -0, 194, 194, 1, 259200, 0x70f05dec -0, 196, 196, 1, 259200, 0x853777d2 -0, 197, 197, 1, 259200, 0x05ea97b2 -0, 199, 199, 1, 259200, 0x03f3a7a2 -0, 200, 200, 1, 259200, 0xf4f7cb7e -0, 202, 202, 1, 259200, 0xd411db6e -0, 203, 203, 1, 259200, 0xfa3afb4e -0, 205, 205, 1, 259200, 0x0a451b3d -0, 206, 206, 1, 259200, 0x94624117 -0, 208, 208, 1, 259200, 0x00996ceb -0, 209, 209, 1, 259200, 0x8c898ccb -0, 211, 211, 1, 259200, 0x5d2496c1 -0, 212, 212, 1, 259200, 0x4f5fce89 -0, 214, 214, 1, 259200, 0xf6a0e671 -0, 215, 215, 1, 259200, 0xcf6f184e -0, 217, 217, 1, 259200, 0x66e2283e -0, 218, 218, 1, 259200, 0x7cd25016 -0, 220, 220, 1, 259200, 0xc2e05a0c -0, 221, 221, 1, 259200, 0x33b767fe -0, 223, 223, 1, 259200, 0x6f5583e2 -0, 224, 224, 1, 259200, 0x19f3a9bc -0, 226, 226, 1, 259200, 0xb3f3b5b0 -0, 227, 227, 1, 259200, 0x6417d590 -0, 229, 229, 1, 259200, 0x7130e580 -0, 230, 230, 1, 259200, 0x4558096b -0, 232, 232, 1, 259200, 0x920c3143 -0, 233, 233, 1, 259200, 0xb7e75123 -0, 235, 235, 1, 259200, 0x38e46113 -0, 236, 236, 1, 259200, 0x96ba90e3 -0, 238, 238, 1, 259200, 0xc65faac9 -0, 239, 239, 1, 259200, 0x7260caa9 -0, 241, 241, 1, 259200, 0x4983cca7 -0, 242, 242, 1, 259200, 0xc04ddc97 -0, 244, 244, 1, 259200, 0x52de0082 -0, 245, 245, 1, 259200, 0xb1cb1c66 -0, 247, 247, 1, 259200, 0x273b364c -0, 248, 248, 1, 259200, 0xd26a661c -0, 250, 250, 1, 259200, 0x9a9599e8 -0, 251, 251, 1, 259200, 0x2e16b5cc -0, 253, 253, 1, 259200, 0x2d4ec9b8 -0, 254, 254, 1, 259200, 0x32d8e998 -0, 256, 256, 1, 259200, 0x5182f988 -0, 257, 257, 1, 259200, 0x48d7157b -0, 259, 259, 1, 259200, 0xa50f335d -0, 260, 260, 1, 259200, 0x3f274f41 -0, 262, 262, 1, 259200, 0xe9776b25 -0, 263, 263, 1, 259200, 0x76728709 -0, 265, 265, 1, 259200, 0x1960a0ef -0, 266, 266, 1, 259200, 0x3d3acac5 -0, 268, 268, 1, 259200, 0x1c6aeaa5 -0, 269, 269, 1, 259200, 0x8bc0148a -0, 271, 271, 1, 259200, 0xa2a72a74 -0, 272, 272, 1, 259200, 0x77db4658 -0, 274, 274, 1, 259200, 0x63705a44 -0, 275, 275, 1, 259200, 0x30db8c12 -0, 277, 277, 1, 259200, 0x32f5a3fa -0, 278, 278, 1, 259200, 0x0107d7c6 -0, 280, 280, 1, 259200, 0xe14707a5 -0, 281, 281, 1, 259200, 0xed7e3379 -0, 283, 283, 1, 259200, 0x55bc416b -0, 284, 284, 1, 259200, 0x1cf1614b -0, 286, 286, 1, 259200, 0x2d507b31 -0, 287, 287, 1, 259200, 0x3fbbaefd -0, 289, 289, 1, 259200, 0x8608d6d5 -0, 290, 290, 1, 259200, 0x169d00ba -0, 292, 292, 1, 259200, 0x7d0b209a -0, 293, 293, 1, 259200, 0xd5943c7e -0, 295, 295, 1, 259200, 0x94e25664 -0, 296, 296, 1, 259200, 0x97447e3c -0, 298, 298, 1, 259200, 0x68bc8436 -0, 299, 299, 1, 259200, 0xb7ee9426 +0, 13, 13, 1, 259200, 0x6779f55d +0, 14, 14, 1, 259200, 0x6779f55d +0, 15, 15, 1, 259200, 0x6779f55d +0, 16, 16, 1, 259200, 0x29aeb27e +0, 17, 17, 1, 259200, 0x29aeb27e +0, 18, 18, 1, 259200, 0x29aeb27e +0, 19, 19, 1, 259200, 0x29aeb27e +0, 20, 20, 1, 259200, 0x29aeb27e +0, 21, 21, 1, 259200, 0x29aeb27e +0, 22, 22, 1, 259200, 0x29aeb27e +0, 23, 23, 1, 259200, 0x29aeb27e +0, 24, 24, 1, 259200, 0x29aeb27e +0, 25, 25, 1, 259200, 0x29aeb27e +0, 26, 26, 1, 259200, 0x29aeb27e +0, 27, 27, 1, 259200, 0x29aeb27e +0, 28, 28, 1, 259200, 0x29aeb27e +0, 29, 29, 1, 259200, 0x29aeb27e +0, 30, 30, 1, 259200, 0x29aeb27e +0, 31, 31, 1, 259200, 0x29aeb27e +0, 32, 32, 1, 259200, 0x6779f55d +0, 33, 33, 1, 259200, 0xcc9cfd55 +0, 34, 34, 1, 259200, 0x0b670d54 +0, 35, 35, 1, 259200, 0x2c45233e +0, 37, 37, 1, 259200, 0x42a92b36 +0, 38, 38, 1, 259200, 0xa61a4120 +0, 40, 40, 1, 259200, 0x22065b06 +0, 41, 41, 1, 259200, 0x7f0775eb +0, 43, 43, 1, 259200, 0x00468fd1 +0, 44, 44, 1, 259200, 0xfd4bb6aa +0, 46, 46, 1, 259200, 0x182fc19f +0, 47, 47, 1, 259200, 0x8814c799 +0, 49, 49, 1, 259200, 0xe28dde82 +0, 50, 50, 1, 259200, 0x038bf46c +0, 52, 52, 1, 259200, 0x8597115e +0, 53, 53, 1, 259200, 0x8b001659 +0, 55, 55, 1, 259200, 0xd5192847 +0, 56, 56, 1, 259200, 0xeb652d42 +0, 58, 58, 1, 259200, 0x84ae551a +0, 59, 59, 1, 259200, 0x171c5f10 +0, 61, 61, 1, 259200, 0xd69a78f6 +0, 62, 62, 1, 259200, 0xf36095d9 +0, 64, 64, 1, 259200, 0x2f509bd3 +0, 65, 65, 1, 259200, 0x49a1bab4 +0, 67, 67, 1, 259200, 0x8248d39b +0, 68, 68, 1, 259200, 0x9969f777 +0, 70, 70, 1, 259200, 0x0cf6fa74 +0, 71, 71, 1, 259200, 0x801f1964 +0, 73, 73, 1, 259200, 0xe7a91c61 +0, 74, 74, 1, 259200, 0xcf402a53 +0, 76, 76, 1, 259200, 0xe08e324b +0, 77, 77, 1, 259200, 0x2afc4439 +0, 79, 79, 1, 259200, 0x71e95825 +0, 80, 80, 1, 259200, 0xa805621b +0, 82, 82, 1, 259200, 0x71547607 +0, 83, 83, 1, 259200, 0x60ed7904 +0, 85, 85, 1, 259200, 0x1cb98fed +0, 86, 86, 1, 259200, 0xc08f92ea +0, 88, 88, 1, 259200, 0x3ebeaad2 +0, 89, 89, 1, 259200, 0xbeb7abd1 +0, 91, 91, 1, 259200, 0xef67c4b8 +0, 92, 92, 1, 259200, 0x03dcc7b5 +0, 94, 94, 1, 259200, 0xb3b8eb91 +0, 95, 95, 1, 259200, 0x3b4af686 +0, 97, 97, 1, 259200, 0xa546ff7d +0, 98, 98, 1, 259200, 0xf5b31378 +0, 100, 100, 1, 259200, 0x32781576 +0, 101, 101, 1, 259200, 0xf00d2962 +0, 103, 103, 1, 259200, 0xf1782c5f +0, 104, 104, 1, 259200, 0x62334645 +0, 106, 106, 1, 259200, 0x53354b40 +0, 107, 107, 1, 259200, 0x9fea5f2c +0, 109, 109, 1, 259200, 0x22906229 +0, 110, 110, 1, 259200, 0xb63f6724 +0, 112, 112, 1, 259200, 0x68018bff +0, 113, 113, 1, 259200, 0x822393f7 +0, 115, 115, 1, 259200, 0x170894f6 +0, 116, 116, 1, 259200, 0x7129addd +0, 118, 118, 1, 259200, 0x8ef0afdb +0, 119, 119, 1, 259200, 0x7dfacac0 +0, 121, 121, 1, 259200, 0x6fffd5b5 +0, 122, 122, 1, 259200, 0x7062ef9b +0, 124, 124, 1, 259200, 0xf6b2f199 +0, 125, 125, 1, 259200, 0x43060891 +0, 127, 127, 1, 259200, 0xb6d40b8e +0, 128, 128, 1, 259200, 0x73182d6c +0, 130, 130, 1, 259200, 0x94e22f6a +0, 131, 131, 1, 259200, 0xd64e3366 +0, 133, 133, 1, 259200, 0x31764f4a +0, 134, 134, 1, 259200, 0x4b485148 +0, 136, 136, 1, 259200, 0x601f5f3a +0, 137, 137, 1, 259200, 0xf6aa7326 +0, 139, 139, 1, 259200, 0x9ac39504 +0, 140, 140, 1, 259200, 0x322e9efa +0, 142, 142, 1, 259200, 0x7308b1e7 +0, 143, 143, 1, 259200, 0x83c2bbdd +0, 145, 145, 1, 259200, 0xfca1ceca +0, 146, 146, 1, 259200, 0x73c7d4c4 +0, 148, 148, 1, 259200, 0xef03e8b0 +0, 149, 149, 1, 259200, 0xfe82eeaa +0, 151, 151, 1, 259200, 0x944600a7 +0, 152, 152, 1, 259200, 0x44f60e99 +0, 154, 154, 1, 259200, 0xa9242384 +0, 155, 155, 1, 259200, 0xd1bb3671 +0, 157, 157, 1, 259200, 0x3160495e +0, 158, 158, 1, 259200, 0x32064b5c +0, 160, 160, 1, 259200, 0x825b6a3d +0, 161, 161, 1, 259200, 0xb6cb7334 +0, 163, 163, 1, 259200, 0xe2678f18 +0, 164, 164, 1, 259200, 0x32379413 +0, 166, 166, 1, 259200, 0x0c2eaafc +0, 167, 167, 1, 259200, 0xcbb7aff7 +0, 169, 169, 1, 259200, 0x78e6b6f0 +0, 170, 170, 1, 259200, 0xcdd4c2e4 +0, 172, 172, 1, 259200, 0xdb94d7cf +0, 173, 173, 1, 259200, 0x2eb9dbcb +0, 175, 175, 1, 259200, 0x4b15edb9 +0, 176, 176, 1, 259200, 0xd7c2f3b3 +0, 178, 178, 1, 259200, 0xb68207ae +0, 179, 179, 1, 259200, 0x88be189d +0, 181, 181, 1, 259200, 0xa3b82b8a +0, 182, 182, 1, 259200, 0xce743085 +0, 184, 184, 1, 259200, 0x969c4b6a +0, 185, 185, 1, 259200, 0xf4fd5560 +0, 187, 187, 1, 259200, 0x439a684d +0, 188, 188, 1, 259200, 0x378e7144 +0, 190, 190, 1, 259200, 0xe64c8b2a +0, 191, 191, 1, 259200, 0xfc2ba70e +0, 193, 193, 1, 259200, 0xee71b203 +0, 194, 194, 1, 259200, 0xc47bc3f1 +0, 196, 196, 1, 259200, 0xe3c5d0e4 +0, 197, 197, 1, 259200, 0x3e2ee0d4 +0, 199, 199, 1, 259200, 0xca2fe8cc +0, 200, 200, 1, 259200, 0x6009faba +0, 202, 202, 1, 259200, 0x5c9a02c1 +0, 203, 203, 1, 259200, 0x09be12b1 +0, 205, 205, 1, 259200, 0x2bc422a1 +0, 206, 206, 1, 259200, 0x8fbc358e +0, 208, 208, 1, 259200, 0xe99b4b78 +0, 209, 209, 1, 259200, 0x49aa5b68 +0, 211, 211, 1, 259200, 0x3a1a6063 +0, 212, 212, 1, 259200, 0xe0be7c47 +0, 214, 214, 1, 259200, 0xc7ec883b +0, 215, 215, 1, 259200, 0xdd00a122 +0, 217, 217, 1, 259200, 0x35c5a91a +0, 218, 218, 1, 259200, 0x6147bd06 +0, 220, 220, 1, 259200, 0x0c78c201 +0, 221, 221, 1, 259200, 0xd038c8fa +0, 223, 223, 1, 259200, 0x04ddd6ec +0, 224, 224, 1, 259200, 0x790ee9d9 +0, 226, 226, 1, 259200, 0xcfd1efd3 +0, 227, 227, 1, 259200, 0xc1ebffc3 +0, 229, 229, 1, 259200, 0x558307ca +0, 230, 230, 1, 259200, 0x5ce019b8 +0, 232, 232, 1, 259200, 0xa3c42da4 +0, 233, 233, 1, 259200, 0x50c13d94 +0, 235, 235, 1, 259200, 0x9e3c458c +0, 236, 236, 1, 259200, 0xf4335d74 +0, 238, 238, 1, 259200, 0x213b6a67 +0, 239, 239, 1, 259200, 0x913c7a57 +0, 241, 241, 1, 259200, 0x7e6e7b56 +0, 242, 242, 1, 259200, 0xc6d7834e +0, 244, 244, 1, 259200, 0x2d70953c +0, 245, 245, 1, 259200, 0xf3a6a32e +0, 247, 247, 1, 259200, 0x438cb021 +0, 248, 248, 1, 259200, 0x4037c809 +0, 250, 250, 1, 259200, 0xce92e1ef +0, 251, 251, 1, 259200, 0x2f21efe1 +0, 253, 253, 1, 259200, 0x3f02f9d7 +0, 254, 254, 1, 259200, 0x5bcf09d6 +0, 256, 256, 1, 259200, 0x782811ce +0, 257, 257, 1, 259200, 0x0aa11fc0 +0, 259, 259, 1, 259200, 0xd11d2eb1 +0, 260, 260, 1, 259200, 0xb4f03ca3 +0, 262, 262, 1, 259200, 0x20ee4a95 +0, 263, 263, 1, 259200, 0x7e2b5887 +0, 265, 265, 1, 259200, 0xe4c1657a +0, 266, 266, 1, 259200, 0x98e07a65 +0, 268, 268, 1, 259200, 0xa2808a55 +0, 269, 269, 1, 259200, 0x7c5d9f40 +0, 271, 271, 1, 259200, 0x99b6aa35 +0, 272, 272, 1, 259200, 0x9b17b827 +0, 274, 274, 1, 259200, 0x212ec21d +0, 275, 275, 1, 259200, 0x3090db04 +0, 277, 277, 1, 259200, 0x4523e6f8 +0, 278, 278, 1, 259200, 0x567900ed +0, 280, 280, 1, 259200, 0xeda518d5 +0, 281, 281, 1, 259200, 0x97932ebf +0, 283, 283, 1, 259200, 0xd70e35b8 +0, 284, 284, 1, 259200, 0x54b845a8 +0, 286, 286, 1, 259200, 0x720e529b +0, 287, 287, 1, 259200, 0x25986c81 +0, 289, 289, 1, 259200, 0xe941806d +0, 290, 290, 1, 259200, 0xd3b69558 +0, 292, 292, 1, 259200, 0x2104a548 +0, 293, 293, 1, 259200, 0xe408b33a +0, 295, 295, 1, 259200, 0x58ddc02d +0, 296, 296, 1, 259200, 0x7a98d419 +0, 298, 298, 1, 259200, 0xe82ed716 +0, 299, 299, 1, 259200, 0x1cdadf0e diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf b/tests/ref/fate/concat-demuxer-extended-lavf-mxf index a3b205539a..543c7d6a8c 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf @@ -1 +1 @@ -0ea04f40869068b282a67e5b8f2a6127 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe +d367d7f6df7292cbf454c6d07fca9b04 *tests/data/fate/concat-demuxer-extended-lavf-mxf.ffprobe diff --git a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 index 9cbc8df831..57b22848b9 100644 --- a/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-extended-lavf-mxf_d10 @@ -1 +1 @@ -88abe27eddff160aafd622ed02c26eb6 *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe +1fac6962d4c5f1070d0d2db5ab7d86aa *tests/data/fate/concat-demuxer-extended-lavf-mxf_d10.ffprobe diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf index fc8034bd29..dcc98e9bdb 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf @@ -78,47 +78,26 @@ video|0|27|1.080000|27|1.080000|1|0.040000|10840|491008|__ audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|502272|K_ video|0|28|1.120000|28|1.120000|1|0.040000|13350|506880|__ audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|520704|K_ -video|0|25|1.000000|24|0.960000|1|0.040000|24801|7168|K_|1 -Strings Metadata -audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|32256|K_|1 -Strings Metadata -video|0|28|1.120000|25|1.000000|1|0.040000|16743|36864|__|1 -Strings Metadata -audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|53760|K_|1 -Strings Metadata -video|0|26|1.040000|26|1.040000|1|0.040000|13812|58368|__|1 -Strings Metadata -audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|72704|K_|1 -Strings Metadata -video|0|27|1.080000|27|1.080000|1|0.040000|13607|77312|__|1 -Strings Metadata -audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|91136|K_|1 -Strings Metadata -video|0|31|1.240000|28|1.120000|1|0.040000|16158|95744|__|1 -Strings Metadata -audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|112128|K_|1 -Strings Metadata -video|0|29|1.160000|29|1.160000|1|0.040000|13943|116736|__|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|3840|131072|K_|1 -Strings Metadata -video|0|30|1.200000|30|1.200000|1|0.040000|11223|135680|__|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|3840|146944|K_|1 -Strings Metadata -video|0|34|1.360000|31|1.240000|1|0.040000|20298|151552|__|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|3840|172032|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|13341|176640|__|1 -Strings Metadata -audio|1|63360|1.320000|63360|1.320000|1920|0.040000|3840|190464|K_|1 -Strings Metadata -video|0|33|1.320000|33|1.320000|1|0.040000|12362|195072|__|1 -Strings Metadata -audio|1|65280|1.360000|65280|1.360000|1920|0.040000|3840|207872|K_|1 -Strings Metadata -video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1 -Strings Metadata -0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +video|0|25|1.000000|24|0.960000|1|0.040000|24801|7168|K_|1|Strings Metadata +audio|1|48000|1.000000|48000|1.000000|1920|0.040000|3840|32256|K_|1|Strings Metadata +video|0|28|1.120000|25|1.000000|1|0.040000|16743|36864|__|1|Strings Metadata +audio|1|49920|1.040000|49920|1.040000|1920|0.040000|3840|53760|K_|1|Strings Metadata +video|0|26|1.040000|26|1.040000|1|0.040000|13812|58368|__|1|Strings Metadata +audio|1|51840|1.080000|51840|1.080000|1920|0.040000|3840|72704|K_|1|Strings Metadata +video|0|27|1.080000|27|1.080000|1|0.040000|13607|77312|__|1|Strings Metadata +audio|1|53760|1.120000|53760|1.120000|1920|0.040000|3840|91136|K_|1|Strings Metadata +video|0|31|1.240000|28|1.120000|1|0.040000|16158|95744|__|1|Strings Metadata +audio|1|55680|1.160000|55680|1.160000|1920|0.040000|3840|112128|K_|1|Strings Metadata +video|0|29|1.160000|29|1.160000|1|0.040000|13943|116736|__|1|Strings Metadata +audio|1|57600|1.200000|57600|1.200000|1920|0.040000|3840|131072|K_|1|Strings Metadata +video|0|30|1.200000|30|1.200000|1|0.040000|11223|135680|__|1|Strings Metadata +audio|1|59520|1.240000|59520|1.240000|1920|0.040000|3840|146944|K_|1|Strings Metadata +video|0|34|1.360000|31|1.240000|1|0.040000|20298|151552|__|1|Strings Metadata +audio|1|61440|1.280000|61440|1.280000|1920|0.040000|3840|172032|K_|1|Strings Metadata +video|0|32|1.280000|32|1.280000|1|0.040000|13341|176640|__|1|Strings Metadata +audio|1|63360|1.320000|63360|1.320000|1920|0.040000|3840|190464|K_|1|Strings Metadata +video|0|33|1.320000|33|1.320000|1|0.040000|12362|195072|__|1|Strings Metadata +audio|1|65280|1.360000|65280|1.360000|1920|0.040000|3840|207872|K_|1|Strings Metadata +video|0|37|1.480000|34|1.360000|1|0.040000|24786|212480|K_|1|Strings Metadata +0|mpeg2video|4|video|[0][0][0][0]|0x0000|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/25|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|51|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001|CPB properties|0|0|0|49152|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|1|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|768000|N/A|N/A|N/A|N/A|50|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 index 59c6372ef2..8937724ed1 100644 --- a/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 +++ b/tests/ref/fate/concat-demuxer-simple1-lavf-mxf_d10 @@ -58,25 +58,15 @@ video|0|28|1.120000|28|1.120000|1|0.040000|150000|4905984|K_ audio|1|53760|1.120000|53760|1.120000|1920|0.040000|7680|5056512|K_ video|0|29|1.160000|29|1.160000|1|0.040000|150000|5118976|K_ audio|1|55680|1.160000|55680|1.160000|1920|0.040000|7680|5269504|K_ -video|0|30|1.200000|30|1.200000|1|0.040000|150000|1072128|K_|1 -Strings Metadata -audio|1|57600|1.200000|57600|1.200000|1920|0.040000|7680|1222656|K_|1 -Strings Metadata -video|0|31|1.240000|31|1.240000|1|0.040000|150000|1285120|K_|1 -Strings Metadata -audio|1|59520|1.240000|59520|1.240000|1920|0.040000|7680|1435648|K_|1 -Strings Metadata -video|0|32|1.280000|32|1.280000|1|0.040000|150000|1498112|K_|1 -Strings Metadata -audio|1|61440|1.280000|61440|1.280000|1920|0.040000|7680|1648640|K_|1 -Strings Metadata -video|0|33|1.320000|33|1.320000|1|0.040000|150000|1711104|K_|1 -Strings Metadata -audio|1|63360|1.320000|63360|1.320000|1920|0.040000|7680|1861632|K_|1 -Strings Metadata -video|0|34|1.360000|34|1.360000|1|0.040000|150000|1924096|K_|1 -Strings Metadata -audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1 -Strings Metadata -0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 +video|0|30|1.200000|30|1.200000|1|0.040000|150000|1072128|K_|1|Strings Metadata +audio|1|57600|1.200000|57600|1.200000|1920|0.040000|7680|1222656|K_|1|Strings Metadata +video|0|31|1.240000|31|1.240000|1|0.040000|150000|1285120|K_|1|Strings Metadata +audio|1|59520|1.240000|59520|1.240000|1920|0.040000|7680|1435648|K_|1|Strings Metadata +video|0|32|1.280000|32|1.280000|1|0.040000|150000|1498112|K_|1|Strings Metadata +audio|1|61440|1.280000|61440|1.280000|1920|0.040000|7680|1648640|K_|1|Strings Metadata +video|0|33|1.320000|33|1.320000|1|0.040000|150000|1711104|K_|1|Strings Metadata +audio|1|63360|1.320000|63360|1.320000|1920|0.040000|7680|1861632|K_|1|Strings Metadata +video|0|34|1.360000|34|1.360000|1|0.040000|150000|1924096|K_|1|Strings Metadata +audio|1|65280|1.360000|65280|1.360000|1920|0.040000|7680|2074624|K_|1|Strings Metadata +0|mpeg2video|0|video|[0][0][0][0]|0x0000|720|608|0|0|0|0|0|1:1|45:38|yuv422p|5|tv|unknown|unknown|unknown|topleft|tb|1|N/A|25/1|25/1|1/25|0|0.000000|N/A|N/A|30000000|N/A|N/A|N/A|N/A|35|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001|CPB properties|30000000|0|0|1212416|-1 1|pcm_s16le|unknown|audio|[0][0][0][0]|0x0000|s16|48000|2|unknown|16|N/A|0/0|0/0|1/48000|0|0.000000|N/A|N/A|1536000|N/A|N/A|N/A|N/A|35|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0x060A2B340101010501010D001300000000000000000000000000000000000001 diff --git a/tests/ref/fate/concat-demuxer-simple2-lavf-ts b/tests/ref/fate/concat-demuxer-simple2-lavf-ts index b9106f0ea9..9603ca21d0 100644 --- a/tests/ref/fate/concat-demuxer-simple2-lavf-ts +++ b/tests/ref/fate/concat-demuxer-simple2-lavf-ts @@ -1,20 +1,20 @@ -video|1|982|0.010911|-2618|-0.029089|3600|0.040000|24801|564|K_MPEGTS Stream ID|224 +video|1|982|0.010911|-2618|-0.029089|3600|0.040000|24801|564|K_|MPEGTS Stream ID|224 -video|1|4582|0.050911|982|0.010911|3600|0.040000|16429|25944|__MPEGTS Stream ID|224 +video|1|4582|0.050911|982|0.010911|3600|0.040000|16429|25944|__|MPEGTS Stream ID|224 -video|1|8182|0.090911|4582|0.050911|3600|0.040000|14508|42864|__MPEGTS Stream ID|224 +video|1|8182|0.090911|4582|0.050911|3600|0.040000|14508|42864|__|MPEGTS Stream ID|224 -video|1|11782|0.130911|8182|0.090911|3600|0.040000|12622|58092|__MPEGTS Stream ID|224 +video|1|11782|0.130911|8182|0.090911|3600|0.040000|12622|58092|__|MPEGTS Stream ID|224 -video|1|15382|0.170911|11782|0.130911|3600|0.040000|13393|71064|__MPEGTS Stream ID|224 +video|1|15382|0.170911|11782|0.130911|3600|0.040000|13393|71064|__|MPEGTS Stream ID|224 -video|1|18982|0.210911|15382|0.170911|3600|0.040000|13092|84788|__MPEGTS Stream ID|224 +video|1|18982|0.210911|15382|0.170911|3600|0.040000|13092|84788|__|MPEGTS Stream ID|224 -video|1|22582|0.250911|18982|0.210911|3600|0.040000|12755|98700|__MPEGTS Stream ID|224 +video|1|22582|0.250911|18982|0.210911|3600|0.040000|12755|98700|__|MPEGTS Stream ID|224 -video|1|26182|0.290911|22582|0.250911|3600|0.040000|12023|111860|__MPEGTS Stream ID|224 +video|1|26182|0.290911|22582|0.250911|3600|0.040000|12023|111860|__|MPEGTS Stream ID|224 -audio|0|0|0.000000|0|0.000000|2351|0.026122|208|152844|K_MPEGTS Stream ID|192 +audio|0|0|0.000000|0|0.000000|2351|0.026122|208|152844|K_|MPEGTS Stream ID|192 audio|0|2351|0.026122|2351|0.026122|2351|0.026122|209|N/A|K_ audio|0|4702|0.052244|4702|0.052244|2351|0.026122|209|N/A|K_ @@ -29,27 +29,27 @@ audio|0|23510|0.261222|23510|0.261222|2351|0.026122|209|N/A|K_ audio|0|25861|0.287344|25861|0.287344|2351|0.026122|209|N/A|K_ audio|0|28212|0.313467|28212|0.313467|2351|0.026122|209|N/A|K_ audio|0|30563|0.339589|30563|0.339589|2351|0.026122|209|N/A|K_ -video|1|29782|0.330911|26182|0.290911|3600|0.040000|14098|124268|__MPEGTS Stream ID|224 +video|1|29782|0.330911|26182|0.290911|3600|0.040000|14098|124268|__|MPEGTS Stream ID|224 -video|1|33382|0.370911|29782|0.330911|3600|0.040000|13329|139120|__MPEGTS Stream ID|224 +video|1|33382|0.370911|29782|0.330911|3600|0.040000|13329|139120|__|MPEGTS Stream ID|224 -video|1|36982|0.410911|33382|0.370911|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|36982|0.410911|33382|0.370911|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|40582|0.450911|36982|0.410911|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|40582|0.450911|36982|0.410911|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|44182|0.490911|40582|0.450911|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|44182|0.490911|40582|0.450911|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|47782|0.530911|44182|0.490911|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|47782|0.530911|44182|0.490911|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|51382|0.570911|47782|0.530911|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|51382|0.570911|47782|0.530911|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 -video|1|54982|0.610911|51382|0.570911|3600|0.040000|13449|240640|__MPEGTS Stream ID|224 +video|1|54982|0.610911|51382|0.570911|3600|0.040000|13449|240640|__|MPEGTS Stream ID|224 -video|1|58582|0.650911|54982|0.610911|3600|0.040000|12398|254552|__MPEGTS Stream ID|224 +video|1|58582|0.650911|54982|0.610911|3600|0.040000|12398|254552|__|MPEGTS Stream ID|224 -video|1|62182|0.690911|58582|0.650911|3600|0.040000|13455|267336|__MPEGTS Stream ID|224 +video|1|62182|0.690911|58582|0.650911|3600|0.040000|13455|267336|__|MPEGTS Stream ID|224 -audio|0|32915|0.365722|32915|0.365722|2351|0.026122|209|308508|K_MPEGTS Stream ID|192 +audio|0|32915|0.365722|32915|0.365722|2351|0.026122|209|308508|K_|MPEGTS Stream ID|192 audio|0|35266|0.391844|35266|0.391844|2351|0.026122|209|N/A|K_ audio|0|37617|0.417967|37617|0.417967|2351|0.026122|209|N/A|K_ @@ -64,17 +64,17 @@ audio|0|56425|0.626944|56425|0.626944|2351|0.026122|209|N/A|K_ audio|0|58776|0.653067|58776|0.653067|2351|0.026122|209|N/A|K_ audio|0|61127|0.679189|61127|0.679189|2351|0.026122|209|N/A|K_ audio|0|63478|0.705311|63478|0.705311|2351|0.026122|209|N/A|K_ -video|1|65782|0.730911|62182|0.690911|3600|0.040000|13836|281624|__MPEGTS Stream ID|224 +video|1|65782|0.730911|62182|0.690911|3600|0.040000|13836|281624|__|MPEGTS Stream ID|224 -video|1|69382|0.770911|65782|0.730911|3600|0.040000|12163|295912|__MPEGTS Stream ID|224 +video|1|69382|0.770911|65782|0.730911|3600|0.040000|12163|295912|__|MPEGTS Stream ID|224 -video|1|72982|0.810911|69382|0.770911|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|72982|0.810911|69382|0.770911|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|76582|0.850911|72982|0.810911|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|76582|0.850911|72982|0.810911|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|80182|0.890911|76582|0.850911|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|80182|0.890911|76582|0.850911|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|65829|0.731433|65829|0.731433|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|65829|0.731433|65829|0.731433|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|68180|0.757556|68180|0.757556|2351|0.026122|209|N/A|K_ audio|0|70531|0.783678|70531|0.783678|2351|0.026122|209|N/A|K_ @@ -86,26 +86,26 @@ audio|0|82286|0.914289|82286|0.914289|2351|0.026122|209|N/A|K_ audio|0|84637|0.940411|84637|0.940411|2351|0.026122|209|N/A|K_ audio|0|86988|0.966533|86988|0.966533|2351|0.026122|209|N/A|K_ audio|0|89339|0.992656|89339|0.992656|2351|0.026122|209|N/A|K_ -video|1|83782|0.930911|80182|0.890911|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|83782|0.930911|80182|0.890911|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|87382|0.970911|83782|0.930911|3600|0.040000|24711|361336|K_ -video|1|91964|1.021822|88364|0.981822|3600|0.040000|24801|564|K_MPEGTS Stream ID|224 +video|1|91964|1.021822|88364|0.981822|3600|0.040000|24801|564|K_|MPEGTS Stream ID|224 -video|1|95564|1.061822|91964|1.021822|3600|0.040000|16429|25944|__MPEGTS Stream ID|224 +video|1|95564|1.061822|91964|1.021822|3600|0.040000|16429|25944|__|MPEGTS Stream ID|224 -video|1|99164|1.101822|95564|1.061822|3600|0.040000|14508|42864|__MPEGTS Stream ID|224 +video|1|99164|1.101822|95564|1.061822|3600|0.040000|14508|42864|__|MPEGTS Stream ID|224 -video|1|102764|1.141822|99164|1.101822|3600|0.040000|12622|58092|__MPEGTS Stream ID|224 +video|1|102764|1.141822|99164|1.101822|3600|0.040000|12622|58092|__|MPEGTS Stream ID|224 -video|1|106364|1.181822|102764|1.141822|3600|0.040000|13393|71064|__MPEGTS Stream ID|224 +video|1|106364|1.181822|102764|1.141822|3600|0.040000|13393|71064|__|MPEGTS Stream ID|224 -video|1|109964|1.221822|106364|1.181822|3600|0.040000|13092|84788|__MPEGTS Stream ID|224 +video|1|109964|1.221822|106364|1.181822|3600|0.040000|13092|84788|__|MPEGTS Stream ID|224 -video|1|113564|1.261822|109964|1.221822|3600|0.040000|12755|98700|__MPEGTS Stream ID|224 +video|1|113564|1.261822|109964|1.221822|3600|0.040000|12755|98700|__|MPEGTS Stream ID|224 -video|1|117164|1.301822|113564|1.261822|3600|0.040000|12023|111860|__MPEGTS Stream ID|224 +video|1|117164|1.301822|113564|1.261822|3600|0.040000|12023|111860|__|MPEGTS Stream ID|224 -audio|0|90982|1.010911|90982|1.010911|2351|0.026122|208|152844|K_MPEGTS Stream ID|192 +audio|0|90982|1.010911|90982|1.010911|2351|0.026122|208|152844|K_|MPEGTS Stream ID|192 audio|0|93333|1.037033|93333|1.037033|2351|0.026122|209|N/A|K_ audio|0|95684|1.063156|95684|1.063156|2351|0.026122|209|N/A|K_ @@ -120,27 +120,27 @@ audio|0|114492|1.272133|114492|1.272133|2351|0.026122|209|N/A|K_ audio|0|116843|1.298256|116843|1.298256|2351|0.026122|209|N/A|K_ audio|0|119194|1.324378|119194|1.324378|2351|0.026122|209|N/A|K_ audio|0|121545|1.350500|121545|1.350500|2351|0.026122|209|N/A|K_ -video|1|120764|1.341822|117164|1.301822|3600|0.040000|14098|124268|__MPEGTS Stream ID|224 +video|1|120764|1.341822|117164|1.301822|3600|0.040000|14098|124268|__|MPEGTS Stream ID|224 -video|1|124364|1.381822|120764|1.341822|3600|0.040000|13329|139120|__MPEGTS Stream ID|224 +video|1|124364|1.381822|120764|1.341822|3600|0.040000|13329|139120|__|MPEGTS Stream ID|224 -video|1|127964|1.421822|124364|1.381822|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|127964|1.421822|124364|1.381822|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|131564|1.461822|127964|1.421822|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|131564|1.461822|127964|1.421822|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|135164|1.501822|131564|1.461822|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|135164|1.501822|131564|1.461822|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|138764|1.541822|135164|1.501822|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|138764|1.541822|135164|1.501822|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|142364|1.581822|138764|1.541822|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|142364|1.581822|138764|1.541822|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 -video|1|145964|1.621822|142364|1.581822|3600|0.040000|13449|240640|__MPEGTS Stream ID|224 +video|1|145964|1.621822|142364|1.581822|3600|0.040000|13449|240640|__|MPEGTS Stream ID|224 -video|1|149564|1.661822|145964|1.621822|3600|0.040000|12398|254552|__MPEGTS Stream ID|224 +video|1|149564|1.661822|145964|1.621822|3600|0.040000|12398|254552|__|MPEGTS Stream ID|224 -video|1|153164|1.701822|149564|1.661822|3600|0.040000|13455|267336|__MPEGTS Stream ID|224 +video|1|153164|1.701822|149564|1.661822|3600|0.040000|13455|267336|__|MPEGTS Stream ID|224 -audio|0|123897|1.376633|123897|1.376633|2351|0.026122|209|308508|K_MPEGTS Stream ID|192 +audio|0|123897|1.376633|123897|1.376633|2351|0.026122|209|308508|K_|MPEGTS Stream ID|192 audio|0|126248|1.402756|126248|1.402756|2351|0.026122|209|N/A|K_ audio|0|128599|1.428878|128599|1.428878|2351|0.026122|209|N/A|K_ @@ -155,17 +155,17 @@ audio|0|147407|1.637856|147407|1.637856|2351|0.026122|209|N/A|K_ audio|0|149758|1.663978|149758|1.663978|2351|0.026122|209|N/A|K_ audio|0|152109|1.690100|152109|1.690100|2351|0.026122|209|N/A|K_ audio|0|154460|1.716222|154460|1.716222|2351|0.026122|209|N/A|K_ -video|1|156764|1.741822|153164|1.701822|3600|0.040000|13836|281624|__MPEGTS Stream ID|224 +video|1|156764|1.741822|153164|1.701822|3600|0.040000|13836|281624|__|MPEGTS Stream ID|224 -video|1|160364|1.781822|156764|1.741822|3600|0.040000|12163|295912|__MPEGTS Stream ID|224 +video|1|160364|1.781822|156764|1.741822|3600|0.040000|12163|295912|__|MPEGTS Stream ID|224 -video|1|163964|1.821822|160364|1.781822|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|163964|1.821822|160364|1.781822|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|167564|1.861822|163964|1.821822|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|167564|1.861822|163964|1.821822|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|171164|1.901822|167564|1.861822|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|171164|1.901822|167564|1.861822|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|156811|1.742344|156811|1.742344|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|156811|1.742344|156811|1.742344|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|159162|1.768467|159162|1.768467|2351|0.026122|209|N/A|K_ audio|0|161513|1.794589|161513|1.794589|2351|0.026122|209|N/A|K_ @@ -177,16 +177,16 @@ audio|0|173268|1.925200|173268|1.925200|2351|0.026122|209|N/A|K_ audio|0|175619|1.951322|175619|1.951322|2351|0.026122|209|N/A|K_ audio|0|177970|1.977444|177970|1.977444|2351|0.026122|209|N/A|K_ audio|0|180321|2.003567|180321|2.003567|2351|0.026122|209|N/A|K_ -video|1|174764|1.941822|171164|1.901822|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|174764|1.941822|171164|1.901822|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|178364|1.981822|174764|1.941822|3600|0.040000|24711|361336|K_ -video|1|139582|1.550911|135982|1.510911|3600|0.040000|12692|311516|__MPEGTS Stream ID|224 +video|1|139582|1.550911|135982|1.510911|3600|0.040000|12692|311516|__|MPEGTS Stream ID|224 -video|1|143182|1.590911|139582|1.550911|3600|0.040000|10824|325052|__MPEGTS Stream ID|224 +video|1|143182|1.590911|139582|1.550911|3600|0.040000|10824|325052|__|MPEGTS Stream ID|224 -video|1|146782|1.630911|143182|1.590911|3600|0.040000|11286|336144|__MPEGTS Stream ID|224 +video|1|146782|1.630911|143182|1.590911|3600|0.040000|11286|336144|__|MPEGTS Stream ID|224 -audio|0|132429|1.471433|132429|1.471433|2351|0.026122|209|386716|K_MPEGTS Stream ID|192 +audio|0|132429|1.471433|132429|1.471433|2351|0.026122|209|386716|K_|MPEGTS Stream ID|192 audio|0|134780|1.497556|134780|1.497556|2351|0.026122|209|N/A|K_ audio|0|137131|1.523678|137131|1.523678|2351|0.026122|209|N/A|K_ @@ -198,18 +198,18 @@ audio|0|148886|1.654289|148886|1.654289|2351|0.026122|209|N/A|K_ audio|0|151237|1.680411|151237|1.680411|2351|0.026122|209|N/A|K_ audio|0|153588|1.706533|153588|1.706533|2351|0.026122|209|N/A|K_ audio|0|155939|1.732656|155939|1.732656|2351|0.026122|209|N/A|K_ -video|1|150382|1.670911|146782|1.630911|3600|0.040000|12678|347800|__MPEGTS Stream ID|224 +video|1|150382|1.670911|146782|1.630911|3600|0.040000|12678|347800|__|MPEGTS Stream ID|224 video|1|153982|1.710911|150382|1.670911|3600|0.040000|24711|361336|K_ -video|1|161182|1.790911|157582|1.750911|3600|0.040000|12135|155852|__MPEGTS Stream ID|224 +video|1|161182|1.790911|157582|1.750911|3600|0.040000|12135|155852|__|MPEGTS Stream ID|224 -video|1|164782|1.830911|161182|1.790911|3600|0.040000|12282|168448|__MPEGTS Stream ID|224 +video|1|164782|1.830911|161182|1.790911|3600|0.040000|12282|168448|__|MPEGTS Stream ID|224 -video|1|168382|1.870911|164782|1.830911|3600|0.040000|24786|181420|K_MPEGTS Stream ID|224 +video|1|168382|1.870911|164782|1.830911|3600|0.040000|24786|181420|K_|MPEGTS Stream ID|224 -video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__MPEGTS Stream ID|224 +video|1|171982|1.910911|168382|1.870911|3600|0.040000|17440|206988|__|MPEGTS Stream ID|224 -video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__MPEGTS Stream ID|224 +video|1|175582|1.950911|171982|1.910911|3600|0.040000|15019|224848|__|MPEGTS Stream ID|224 0|mp2|unknown|audio|[3][0][0][0]|0x0003|s16p|44100|1|mono|0|N/A|0/0|0/0|1/90000|0|0.000000|N/A|N/A|64000|N/A|N/A|N/A|N/A|89|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 0 -1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1 +1|mpeg2video|4|video|[2][0][0][0]|0x0002|352|288|0|0|0|0|1|1:1|11:9|yuv420p|8|tv|unknown|unknown|unknown|left|progressive|1|N/A|25/1|25/1|1/90000|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|N/A|60|22|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|this is stream 1|CPB properties|0|0|0|49152|-1 diff --git a/tests/ref/fate/copy-shortest1 b/tests/ref/fate/copy-shortest1 new file mode 100644 index 0000000000..69204b373a --- /dev/null +++ b/tests/ref/fate/copy-shortest1 @@ -0,0 +1,124 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 30, 0e11a510b0c7831954402f81dd258188 +#tb 0: 1/51200 +#media_type 0: video +#codec_id 0: mpeg4 +#dimensions 0: 352x288 +#sar 0: 1/1 +#tb 1: 1/44100 +#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 +0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a +1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 +0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504 +1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 +0, 4096, 4096, 2048, 1167, d3b895191e8a06d19bbc8ac90e564b3b +1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade +0, 6144, 6144, 2048, 1274, 272f548f13dd6a45a5cd187f0e43e635 +1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 +0, 8192, 8192, 2048, 1361, a0c67fc195fe867ae240dc8c48f85b2e +1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 +0, 10240, 10240, 2048, 1415, f7a3746adb348eb00042b3eccff54a87 +1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 +1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 +0, 12288, 12288, 2048, 1421, 8396b1c23f7d39f6f73c3469826317d6 +1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 +0, 14336, 14336, 2048, 1474, a9c493c020d710af7f2c98b9aae846ff +1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 +0, 16384, 16384, 2048, 1467, b801d1a76c84923ab813e9a5d9ebdb78 +1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae +0, 18432, 18432, 2048, 1469, 22f7fcd055bf124436de9a9432f7c9d2 +1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 +0, 20480, 20480, 2048, 1506, da18f30d7008f2307ec51863a9873afd +1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 +0, 22528, 22528, 2048, 1520, 2c7d44ca3485373af6cfb3e44e495bf7 +1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c +0, 24576, 24576, 2048, 8524, 0634c69955cbffe94f4e15b288557cac +1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb +1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 +0, 26624, 26624, 2048, 1079, f081cbd559dab2b579f40d2fa988a959 +1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 +0, 28672, 28672, 2048, 1343, fdf8069cd511f4fa185748118acfb72e +1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 +0, 30720, 30720, 2048, 1486, e72dfcd069f5be3a30310002b1b5e252 +1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc +0, 32768, 32768, 2048, 1491, 710c5421d44a8c9356c1477cbcd27c0e +1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 +0, 34816, 34816, 2048, 1504, 16a6d624b8175f1191ede25e2d588b92 +1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 +0, 36864, 36864, 2048, 1481, 8696aa412629328687bda5e88dd40b81 +1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb +0, 38912, 38912, 2048, 1521, 3c974bf799b8e35d295c6567ffeb7276 +1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b +1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 +0, 40960, 40960, 2048, 1514, 1a54ec5296f1551a7f67c515e40ca646 +1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d +0, 43008, 43008, 2048, 1562, d285916a1c7a2fb9f37d18bfa977e075 +1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 +0, 45056, 45056, 2048, 1562, 320c26adae1dad1741e02febdbd5b916 +1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae +0, 47104, 47104, 2048, 1629, 60c6ebd71f641ebcff9997ee338d82bf +1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed +0, 49152, 49152, 2048, 9634, b72deda826b002179c46789e92c07978 +1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd +0, 51200, 51200, 2048, 1239, 407105508656c920761e60c90540ee18 +1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 +1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 +0, 53248, 53248, 2048, 1568, 1e5b232eaf9f35846ae25b881f658e5c +1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 +0, 55296, 55296, 2048, 1641, f79725e348ed7796f2be7c153ce32580 +1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca +0, 57344, 57344, 2048, 1735, ae14fbdbf8777d88077818db0ae346b3 +1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 +0, 59392, 59392, 2048, 1760, e943dc0f9ed56fbca1af43c3c3c6dea1 +1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 +0, 61440, 61440, 2048, 1798, efb1c91f9aee5c84c92e8cd5a5b58783 +1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 +0, 63488, 63488, 2048, 1830, 7aa74080b344e63280854570f701e2b8 +1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab +0, 65536, 65536, 2048, 1835, 566fa13f73b9aa63eed50511b112b191 +1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a +1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c +0, 67584, 67584, 2048, 1902, 95933f1710291419d0febd37d5878362 +1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f +0, 69632, 69632, 2048, 1886, 5a8e4c7557ec0d09d40fbfabc5b92e63 +1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 +0, 71680, 71680, 2048, 1949, 3f81e2b8821c22f89501feafebb9d618 +1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 +0, 73728, 73728, 2048, 10776, 29e4a6fdc625965feae7faa8ab239db1 +1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 +0, 75776, 75776, 2048, 1413, 4b5bde19c84eca2c776f6ac45163a0a5 +1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 +0, 77824, 77824, 2048, 1731, 7f46b3e146e52fd500dbf53a3c744662 +1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e +0, 79872, 79872, 2048, 1888, 2bd4182a0fe98db2990c8e39c0500872 +1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d +1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 +0, 81920, 81920, 2048, 1989, f3bf07391ef46cba98eb78fdc3707fa3 +1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 +0, 83968, 83968, 2048, 1949, 0650751332acc5d5f96f292ffc4add21 +1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb +0, 86016, 86016, 2048, 1956, d52d57b697f4ec90bb1f69fd7ece1952 +1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 +0, 88064, 88064, 2048, 2012, e25c0bb0ec726fe5c9ade88cf7ae9a19 +1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b +0, 90112, 90112, 2048, 1995, eb0377542bc15580ef8f772ce6f506bd +1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 +0, 92160, 92160, 2048, 2078, 7aa93cd366118984932da377f4743de6 +1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 +0, 94208, 94208, 2048, 2116, 9d8c672e97c27ed4e3281bb10481914a +1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 +1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 +0, 96256, 96256, 2048, 2024, 18d42dbec2fa24fd30374d79a054cd4f +1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 +0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2 +1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af +0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d +1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-shortest2 b/tests/ref/fate/copy-shortest2 new file mode 100644 index 0000000000..69204b373a --- /dev/null +++ b/tests/ref/fate/copy-shortest2 @@ -0,0 +1,124 @@ +#format: frame checksums +#version: 2 +#hash: MD5 +#extradata 0, 30, 0e11a510b0c7831954402f81dd258188 +#tb 0: 1/51200 +#media_type 0: video +#codec_id 0: mpeg4 +#dimensions 0: 352x288 +#sar 0: 1/1 +#tb 1: 1/44100 +#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 +0, 0, 0, 2048, 8719, bbea2a7487d61d39a0b2f2fe62a4df4a +1, 1280, 1280, 1536, 418, 6e79527e2af3448d7a0e4a8e29cd9722 +0, 2048, 2048, 2048, 975, 94f30e410595452ee981d96224516504 +1, 2816, 2816, 1536, 418, cf49595ac385e497672e5a814f7bcd79 +0, 4096, 4096, 2048, 1167, d3b895191e8a06d19bbc8ac90e564b3b +1, 4352, 4352, 1536, 418, 846982243d330ab782f0120988d52ade +0, 6144, 6144, 2048, 1274, 272f548f13dd6a45a5cd187f0e43e635 +1, 5888, 5888, 1536, 418, 77b2d15948434a4831e30c47b8214591 +0, 8192, 8192, 2048, 1361, a0c67fc195fe867ae240dc8c48f85b2e +1, 7424, 7424, 1536, 418, 4fce87d5cce10f6d0268fb398c385af5 +0, 10240, 10240, 2048, 1415, f7a3746adb348eb00042b3eccff54a87 +1, 8960, 8960, 1536, 418, 963f2dac9af4672809521f2174b78f10 +1, 10496, 10496, 1536, 418, eb7a20193c157b02f7b5d5abf802af24 +0, 12288, 12288, 2048, 1421, 8396b1c23f7d39f6f73c3469826317d6 +1, 12032, 12032, 1536, 418, 219b234a1e01d3538bfe09fda58b3289 +0, 14336, 14336, 2048, 1474, a9c493c020d710af7f2c98b9aae846ff +1, 13568, 13568, 1536, 418, ef7bd3e9c13f03aa6676629101a9a8a0 +0, 16384, 16384, 2048, 1467, b801d1a76c84923ab813e9a5d9ebdb78 +1, 15104, 15104, 1536, 418, c5dda974df7e418d9036dff134aad2ae +0, 18432, 18432, 2048, 1469, 22f7fcd055bf124436de9a9432f7c9d2 +1, 16640, 16640, 1536, 418, 48e7a9f574654dd95a325cfec5072254 +0, 20480, 20480, 2048, 1506, da18f30d7008f2307ec51863a9873afd +1, 18176, 18176, 1536, 418, 737d867e328377a3e6623f77f646ea61 +0, 22528, 22528, 2048, 1520, 2c7d44ca3485373af6cfb3e44e495bf7 +1, 19712, 19712, 1536, 418, 5e2a004ad90ba069cecd9fdc1652388c +0, 24576, 24576, 2048, 8524, 0634c69955cbffe94f4e15b288557cac +1, 21248, 21248, 1536, 418, c694e51e609bdd00749a04294cbd60fb +1, 22784, 22784, 1536, 418, 6b787ffae0063d9910deebc8b3e98fd4 +0, 26624, 26624, 2048, 1079, f081cbd559dab2b579f40d2fa988a959 +1, 24320, 24320, 1536, 418, eb6d62198a5472a1c179d42cde60b869 +0, 28672, 28672, 2048, 1343, fdf8069cd511f4fa185748118acfb72e +1, 25856, 25856, 1536, 418, 70a6c8e61e8d75f7a310bc7294ad38f6 +0, 30720, 30720, 2048, 1486, e72dfcd069f5be3a30310002b1b5e252 +1, 27392, 27392, 1536, 418, 6847924a11575b3628ccdfd81a2fb1dc +0, 32768, 32768, 2048, 1491, 710c5421d44a8c9356c1477cbcd27c0e +1, 28928, 28928, 1536, 418, 6f76bbe03d8b4e0080226247e0e54f96 +0, 34816, 34816, 2048, 1504, 16a6d624b8175f1191ede25e2d588b92 +1, 30464, 30464, 1536, 418, c946a8d690aa31fde929678b594cc432 +0, 36864, 36864, 2048, 1481, 8696aa412629328687bda5e88dd40b81 +1, 32000, 32000, 1536, 418, 3add3833b86a38c229faf8e602f83dcb +0, 38912, 38912, 2048, 1521, 3c974bf799b8e35d295c6567ffeb7276 +1, 33536, 33536, 1536, 418, cb51e6a41f5c4a5f01dd94f58210112b +1, 35072, 35072, 1536, 418, 66c3570cb8c11386b0601fe4a6eb7ee0 +0, 40960, 40960, 2048, 1514, 1a54ec5296f1551a7f67c515e40ca646 +1, 36608, 36608, 1536, 418, 8b986c15b9ab86432c43cedd1a182e8d +0, 43008, 43008, 2048, 1562, d285916a1c7a2fb9f37d18bfa977e075 +1, 38144, 38144, 1536, 418, 0dd29cc7f63f2afac3eec5e5944165e7 +0, 45056, 45056, 2048, 1562, 320c26adae1dad1741e02febdbd5b916 +1, 39680, 39680, 1536, 418, c4c14deb03d5048f8c6101260c617fae +0, 47104, 47104, 2048, 1629, 60c6ebd71f641ebcff9997ee338d82bf +1, 41216, 41216, 1536, 418, 4a3480d888fa0dd49a7bbf2669b5d3ed +0, 49152, 49152, 2048, 9634, b72deda826b002179c46789e92c07978 +1, 42752, 42752, 1536, 418, aaeabe149b9185a6f09c271eb2c656dd +0, 51200, 51200, 2048, 1239, 407105508656c920761e60c90540ee18 +1, 44288, 44288, 1536, 418, 0995488ad1bb84ec4a3e738b568484a4 +1, 45824, 45824, 1536, 418, baa39bdfd9f47f7d312312985f59fb72 +0, 53248, 53248, 2048, 1568, 1e5b232eaf9f35846ae25b881f658e5c +1, 47360, 47360, 1536, 418, c25bac736a8c356d0a0f9c9299f88880 +0, 55296, 55296, 2048, 1641, f79725e348ed7796f2be7c153ce32580 +1, 48896, 48896, 1536, 418, 85378fd6c8b49a1f4c5490ab1e4013ca +0, 57344, 57344, 2048, 1735, ae14fbdbf8777d88077818db0ae346b3 +1, 50432, 50432, 1536, 418, 528e28031145f07336cd2a1b9b324ca6 +0, 59392, 59392, 2048, 1760, e943dc0f9ed56fbca1af43c3c3c6dea1 +1, 51968, 51968, 1536, 418, cc9b907fc92fffc61f7e41cdb863d586 +0, 61440, 61440, 2048, 1798, efb1c91f9aee5c84c92e8cd5a5b58783 +1, 53504, 53504, 1536, 418, fe2f2ca279b14d7053349111578b48c0 +0, 63488, 63488, 2048, 1830, 7aa74080b344e63280854570f701e2b8 +1, 55040, 55040, 1536, 418, 5f2c6037aa4b89572a4ed712082ae2ab +0, 65536, 65536, 2048, 1835, 566fa13f73b9aa63eed50511b112b191 +1, 56576, 56576, 1536, 418, 17a096694df972c2ef3a9abbe0a9cd6a +1, 58112, 58112, 1536, 418, c96a64bbfd1aae269e44bfdaea7c8a9c +0, 67584, 67584, 2048, 1902, 95933f1710291419d0febd37d5878362 +1, 59648, 59648, 1536, 418, 5f9297244e107134c49fc4982f5a7c1f +0, 69632, 69632, 2048, 1886, 5a8e4c7557ec0d09d40fbfabc5b92e63 +1, 61184, 61184, 1536, 418, da740d2d75b51d6e28bcb068f6a90d41 +0, 71680, 71680, 2048, 1949, 3f81e2b8821c22f89501feafebb9d618 +1, 62720, 62720, 1536, 418, 76e6bbbbfa0692659d0d84a30dcfff34 +0, 73728, 73728, 2048, 10776, 29e4a6fdc625965feae7faa8ab239db1 +1, 64256, 64256, 1536, 418, 0bd304182f1693b18c46b0faa682b159 +0, 75776, 75776, 2048, 1413, 4b5bde19c84eca2c776f6ac45163a0a5 +1, 65792, 65792, 1536, 418, ecf7bd4ba9161338ce2cefc1fdd06098 +0, 77824, 77824, 2048, 1731, 7f46b3e146e52fd500dbf53a3c744662 +1, 67328, 67328, 1536, 418, 4953c0e441ca0ca2e1970b8b31d6c70e +0, 79872, 79872, 2048, 1888, 2bd4182a0fe98db2990c8e39c0500872 +1, 68864, 68864, 1536, 418, 4eb7f24aa46b8f0e6b47d0ca6ec0d56d +1, 70400, 70400, 1536, 418, df4d73a6acccd3be6663188f4baab996 +0, 81920, 81920, 2048, 1989, f3bf07391ef46cba98eb78fdc3707fa3 +1, 71936, 71936, 1536, 418, 5e60f266106b86f19749b64d86b11f43 +0, 83968, 83968, 2048, 1949, 0650751332acc5d5f96f292ffc4add21 +1, 73472, 73472, 1536, 418, cedea148c5f7ddba6f0fbcbe17e6bfbb +0, 86016, 86016, 2048, 1956, d52d57b697f4ec90bb1f69fd7ece1952 +1, 75008, 75008, 1536, 416, 97655498b413a59b3f0f6bdc25f69084 +0, 88064, 88064, 2048, 2012, e25c0bb0ec726fe5c9ade88cf7ae9a19 +1, 76544, 76544, 1536, 418, 0bea3f23db7aafefe50710310af25a9b +0, 90112, 90112, 2048, 1995, eb0377542bc15580ef8f772ce6f506bd +1, 78080, 78080, 1536, 418, e763b383810d9a4645901c0d93f98a32 +0, 92160, 92160, 2048, 2078, 7aa93cd366118984932da377f4743de6 +1, 79616, 79616, 1536, 418, f090bb15688066a9c5129348f86245e7 +0, 94208, 94208, 2048, 2116, 9d8c672e97c27ed4e3281bb10481914a +1, 81152, 81152, 1536, 418, beb8658ede31b44326de936b28a2d740 +1, 82688, 82688, 1536, 418, 53987c0214550f387ce03093b83f4225 +0, 96256, 96256, 2048, 2024, 18d42dbec2fa24fd30374d79a054cd4f +1, 84224, 84224, 1536, 418, d3c37c202144070892528cc0a0ff3112 +0, 98304, 98304, 2048, 11182, e35a2ab846029effdbca0e43639717f2 +1, 85760, 85760, 1536, 418, cf52ea7fc69e4c5bc8f75b354dfe60af +0, 100352, 100352, 2048, 1423, f480272c7d0b97834bc8ea36cceca61d +1, 87296, 87296, 1536, 418, 78ab22657a1b6c8a0e5b8612ceb8081d diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074 index 4748296c2a..2ef7e702cd 100644 --- a/tests/ref/fate/copy-trac3074 +++ b/tests/ref/fate/copy-trac3074 @@ -1,4 +1,4 @@ -452d91e7c6889b787717fef25b6fce43 *tests/data/fate/copy-trac3074.mp4 +36fcc0a62695bcf93068fcfe68283ee9 *tests/data/fate/copy-trac3074.mp4 334016 tests/data/fate/copy-trac3074.mp4 #tb 0: 1/48000 #media_type 0: audio diff --git a/tests/ref/fate/dcinema-encode b/tests/ref/fate/dcinema-encode index 03e6e6ef6c..cc53488be1 100644 --- a/tests/ref/fate/dcinema-encode +++ b/tests/ref/fate/dcinema-encode @@ -10,21 +10,21 @@ #stream#, dts, pts, duration, size, hash 0, 0, 0, 341, 4092, 697cddfcd0e21f24782af0705b7048f3 0, 341, 341, 341, 4092, a057b18cd493923fed33c18578f61e0b -0, 682, 682, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 -0, 1023, 1023, 341, 4092, 4de78d332ce2047014880a110c160dc2 +0, 683, 683, 341, 4092, f4eacfd888566040067b8e5ce7d276c6 +0, 1024, 1024, 341, 4092, 4de78d332ce2047014880a110c160dc2 0, 1364, 1364, 341, 4092, 138ee3fc206538feca6de3d6d62d08eb -0, 1705, 1705, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 -0, 2046, 2046, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 +0, 1706, 1706, 341, 4092, 187a2f2998aa1c0ba0130c57dd1d6c86 +0, 2047, 2047, 341, 4092, 54e6c3db8a5f8c09b47f025659a36b17 0, 2387, 2387, 341, 4092, 8abfdf44a24c158429c71e01cee31e20 -0, 2728, 2728, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 -0, 3069, 3069, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 -0, 3410, 3410, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 +0, 2729, 2729, 341, 4092, bd08f5018edc5dc4520739e913ed89a3 +0, 3070, 3070, 341, 4092, 9f60ba4275646344e4a9b3c647efffe9 +0, 3411, 3411, 341, 4092, 00cefc1f27230cdd06ecd43132e16327 0, 3751, 3751, 341, 4092, d4d13047cd639ed722a4ae1bc1f06991 -0, 4092, 4092, 341, 4092, 16b227e4f968c11cba279506f00d5172 -0, 4433, 4433, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a +0, 4093, 4093, 341, 4092, 16b227e4f968c11cba279506f00d5172 +0, 4434, 4434, 341, 4092, 70f4046f709fdd4d80e2f2ffc862f21a 0, 4774, 4774, 341, 4092, adbef4b4ef728f0c2a31b4b0baba50a0 -0, 5115, 5115, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa -0, 5456, 5456, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 +0, 5116, 5116, 341, 4092, fe009b6cc96b9d1098dcc5fba0e6b3fa +0, 5457, 5457, 341, 4092, 4462b2f1654c9b31fdd7ab04ffb84192 0, 5797, 5797, 341, 4092, 2e96ba3bd13de03f9cfdc2b8c3ea0620 -0, 6138, 6138, 341, 4092, 395c920f10cce6670029a98095eba027 -0, 6479, 6479, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 +0, 6139, 6139, 341, 4092, 395c920f10cce6670029a98095eba027 +0, 6480, 6480, 341, 4092, 28d4c2f6364f31cb61f4aa144badc734 diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact index 12565d2600..911777069a 100644 --- a/tests/ref/fate/ffprobe_compact +++ b/tests/ref/fate/ffprobe_compact @@ -1,32 +1,32 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=2048|pos=647|flags=K_ -frame|media_type=audio|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=1024|pkt_duration_time=0.023220|pkt_pos=647|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=230400|pos=2722|flags=K_ -frame|media_type=video|stream_index=1|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=2048|pkt_duration_time=0.040000|pkt_pos=2722|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=30000|pos=233143|flags=K_ -frame|media_type=video|stream_index=2|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=2048|pkt_duration_time=0.040000|pkt_pos=233143|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|size=2048|pos=263148|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=1024|pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263148|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=230400|pos=265226|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265226|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=30000|pos=495650|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495650|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|size=2048|pos=525655|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=2048|pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525655|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|size=2048|pos=527726|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=3072|pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527726|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=230400|pos=529804|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529804|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=30000|pos=760228|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760228|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|size=2048|pos=790233|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=4096|pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790233|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown -packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=393|duration_time=0.008912|size=786|pos=792304|flags=K_ -frame|media_type=audio|stream_index=0|key_frame=1|pts=5120|pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=393|pkt_duration_time=0.008912|pkt_pos=792304|pkt_size=786|sample_fmt=s16|nb_samples=393|channels=1|channel_layout=unknown -packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=230400|pos=793120|flags=K_ -frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=793120|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified -packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=30000|pos=1023544|flags=K_ -frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1023544|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=2048|pos=669|flags=K_ +frame|media_type=audio|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=1024|pkt_duration_time=0.023220|pkt_pos=669|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=230400|pos=2744|flags=K_ +frame|media_type=video|stream_index=1|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=2048|pkt_duration_time=0.040000|pkt_pos=2744|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=30000|pos=233165|flags=K_ +frame|media_type=video|stream_index=2|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=2048|pkt_duration_time=0.040000|pkt_pos=233165|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|size=2048|pos=263170|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=1024|pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=263170|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=230400|pos=265248|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=265248|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=30000|pos=495672|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=495672|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|size=2048|pos=525677|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=2048|pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=525677|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|size=2048|pos=527748|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=3072|pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=527748|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=230400|pos=529826|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=529826|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=30000|pos=760250|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=760250|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|size=2048|pos=790255|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=4096|pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|pkt_duration=1024|pkt_duration_time=0.023220|pkt_pos=790255|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown +packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=393|duration_time=0.008912|size=786|pos=792326|flags=K_ +frame|media_type=audio|stream_index=0|key_frame=1|pts=5120|pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|pkt_duration=393|pkt_duration_time=0.008912|pkt_pos=792326|pkt_size=786|sample_fmt=s16|nb_samples=393|channels=1|channel_layout=unknown +packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=230400|pos=793142|flags=K_ +frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=793142|pkt_size=230400|width=320|height=240|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified +packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=30000|pos=1023566|flags=K_ +frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|pkt_duration=2048|pkt_duration_time=0.040000|pkt_pos=1023566|pkt_size=30000|width=100|height=100|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=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:E=mc²|tag:encoder=Lavc pcm_s16le -stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo +stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt|tag:encoder=Lavc rawvideo stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:encoder=Lavc rawvideo -format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1053624|bit_rate=70241600|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ +format|filename=tests/data/ffprobe-test.nut|nb_streams=3|nb_programs=0|format_name=nut|start_time=0.000000|duration=0.120000|size=1053646|bit_rate=70243066|probe_score=100|tag:title=ffprobe test file|tag:comment='A comment with CSV, XML & JSON special chars': |tag:comment2=I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv index 0bbc15e4d5..fd6bb242c9 100644 --- a/tests/ref/fate/ffprobe_csv +++ b/tests/ref/fate/ffprobe_csv @@ -1,32 +1,32 @@ -packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,647,K_ -frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,647,2048,s16,1024,1,unknown -packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2722,K_ -frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2722,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,0,0.000000,0,0.000000,2048,0.040000,30000,233143,K_ -frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233143,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,2048,263148,K_ -frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263148,2048,s16,1024,1,unknown -packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265226,K_ -frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265226,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,30000,495650,K_ -frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495650,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,2048,525655,K_ -frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525655,2048,s16,1024,1,unknown -packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527726,K_ -frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527726,2048,s16,1024,1,unknown -packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529804,K_ -frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529804,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,30000,760228,K_ -frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760228,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,2048,790233,K_ -frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790233,2048,s16,1024,1,unknown -packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792304,K_ -frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,393,0.008912,792304,786,s16,393,1,unknown -packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793120,K_ -frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793120,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified -packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,30000,1023544,K_ -frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023544,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,669,K_ +frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,669,2048,s16,1024,1,unknown +packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2744,K_ +frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2744,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,0,0.000000,0,0.000000,2048,0.040000,30000,233165,K_ +frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233165,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,2048,263170,K_ +frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263170,2048,s16,1024,1,unknown +packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265248,K_ +frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265248,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,30000,495672,K_ +frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495672,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,2048,525677,K_ +frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525677,2048,s16,1024,1,unknown +packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527748,K_ +frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527748,2048,s16,1024,1,unknown +packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529826,K_ +frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529826,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,30000,760250,K_ +frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760250,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,2048,790255,K_ +frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790255,2048,s16,1024,1,unknown +packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792326,K_ +frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,393,0.008912,792326,786,s16,393,1,unknown +packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793142,K_ +frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793142,230400,320,240,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified +packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,30000,1023566,K_ +frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023566,30000,100,100,rgb24,1:1,I,0,0,0,0,0,unknown,unknown,unknown,unknown,unspecified stream,0,pcm_s16le,unknown,audio,PSD[16],0x10445350,s16,44100,1,unknown,16,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,N/A,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,mc²,Lavc pcm_s16le -stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,0,0,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo +stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,0,0,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,foobar,field-and-tags-conflict-attempt,Lavc rawvideo stream,2,rawvideo,unknown,video,RGB[24],0x18424752,100,100,100,100,0,0,0,1:1,1:1,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo -format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1053624,70241600,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ +format,tests/data/ffprobe-test.nut,3,0,nut,0.000000,0.120000,1053646,70243066,100,ffprobe test file,"'A comment with CSV, XML & JSON special chars': ",I ♥ Üñîçød€ diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default index 54e992c406..d3d90fa5d6 100644 --- a/tests/ref/fate/ffprobe_default +++ b/tests/ref/fate/ffprobe_default @@ -8,7 +8,7 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 size=2048 -pos=647 +pos=669 flags=K_ [/PACKET] [FRAME] @@ -23,7 +23,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=647 +pkt_pos=669 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -40,7 +40,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=230400 -pos=2722 +pos=2744 flags=K_ [/PACKET] [FRAME] @@ -55,7 +55,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2722 +pkt_pos=2744 pkt_size=230400 width=320 height=240 @@ -83,7 +83,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=30000 -pos=233143 +pos=233165 flags=K_ [/PACKET] [FRAME] @@ -98,7 +98,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233143 +pkt_pos=233165 pkt_size=30000 width=100 height=100 @@ -126,7 +126,7 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 size=2048 -pos=263148 +pos=263170 flags=K_ [/PACKET] [FRAME] @@ -141,7 +141,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263148 +pkt_pos=263170 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -158,7 +158,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=230400 -pos=265226 +pos=265248 flags=K_ [/PACKET] [FRAME] @@ -173,7 +173,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265226 +pkt_pos=265248 pkt_size=230400 width=320 height=240 @@ -201,7 +201,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=30000 -pos=495650 +pos=495672 flags=K_ [/PACKET] [FRAME] @@ -216,7 +216,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495650 +pkt_pos=495672 pkt_size=30000 width=100 height=100 @@ -244,7 +244,7 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 size=2048 -pos=525655 +pos=525677 flags=K_ [/PACKET] [FRAME] @@ -259,7 +259,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525655 +pkt_pos=525677 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -276,7 +276,7 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 size=2048 -pos=527726 +pos=527748 flags=K_ [/PACKET] [FRAME] @@ -291,7 +291,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527726 +pkt_pos=527748 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -308,7 +308,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=230400 -pos=529804 +pos=529826 flags=K_ [/PACKET] [FRAME] @@ -323,7 +323,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529804 +pkt_pos=529826 pkt_size=230400 width=320 height=240 @@ -351,7 +351,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=30000 -pos=760228 +pos=760250 flags=K_ [/PACKET] [FRAME] @@ -366,7 +366,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760228 +pkt_pos=760250 pkt_size=30000 width=100 height=100 @@ -394,7 +394,7 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 size=2048 -pos=790233 +pos=790255 flags=K_ [/PACKET] [FRAME] @@ -409,7 +409,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790233 +pkt_pos=790255 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -426,7 +426,7 @@ dts_time=0.116100 duration=393 duration_time=0.008912 size=786 -pos=792304 +pos=792326 flags=K_ [/PACKET] [FRAME] @@ -441,7 +441,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=393 pkt_duration_time=0.008912 -pkt_pos=792304 +pkt_pos=792326 pkt_size=786 sample_fmt=s16 nb_samples=393 @@ -458,7 +458,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=230400 -pos=793120 +pos=793142 flags=K_ [/PACKET] [FRAME] @@ -473,7 +473,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=793120 +pkt_pos=793142 pkt_size=230400 width=320 height=240 @@ -501,7 +501,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=30000 -pos=1023544 +pos=1023566 flags=K_ [/PACKET] [FRAME] @@ -516,7 +516,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1023544 +pkt_pos=1023566 pkt_size=30000 width=100 height=100 @@ -619,7 +619,7 @@ bits_per_raw_sample=N/A nb_frames=N/A nb_read_frames=4 nb_read_packets=4 -DISPOSITION:default=0 +DISPOSITION:default=1 DISPOSITION:dub=0 DISPOSITION:original=0 DISPOSITION:comment=0 @@ -705,8 +705,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1053624 -bit_rate=70241600 +size=1053646 +bit_rate=70243066 probe_score=100 TAG:title=ffprobe test file TAG:comment='A comment with CSV, XML & JSON special chars': diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat index 4b0b4b3881..e77dec6b84 100644 --- a/tests/ref/fate/ffprobe_flat +++ b/tests/ref/fate/ffprobe_flat @@ -7,7 +7,7 @@ packets_and_frames.packet.0.dts_time="0.000000" packets_and_frames.packet.0.duration=1024 packets_and_frames.packet.0.duration_time="0.023220" packets_and_frames.packet.0.size="2048" -packets_and_frames.packet.0.pos="647" +packets_and_frames.packet.0.pos="669" packets_and_frames.packet.0.flags="K_" packets_and_frames.frame.0.media_type="audio" packets_and_frames.frame.0.stream_index=0 @@ -20,7 +20,7 @@ packets_and_frames.frame.0.best_effort_timestamp=0 packets_and_frames.frame.0.best_effort_timestamp_time="0.000000" packets_and_frames.frame.0.pkt_duration=1024 packets_and_frames.frame.0.pkt_duration_time="0.023220" -packets_and_frames.frame.0.pkt_pos="647" +packets_and_frames.frame.0.pkt_pos="669" packets_and_frames.frame.0.pkt_size="2048" packets_and_frames.frame.0.sample_fmt="s16" packets_and_frames.frame.0.nb_samples=1024 @@ -35,7 +35,7 @@ packets_and_frames.packet.1.dts_time="0.000000" packets_and_frames.packet.1.duration=2048 packets_and_frames.packet.1.duration_time="0.040000" packets_and_frames.packet.1.size="230400" -packets_and_frames.packet.1.pos="2722" +packets_and_frames.packet.1.pos="2744" packets_and_frames.packet.1.flags="K_" packets_and_frames.frame.1.media_type="video" packets_and_frames.frame.1.stream_index=1 @@ -48,7 +48,7 @@ packets_and_frames.frame.1.best_effort_timestamp=0 packets_and_frames.frame.1.best_effort_timestamp_time="0.000000" packets_and_frames.frame.1.pkt_duration=2048 packets_and_frames.frame.1.pkt_duration_time="0.040000" -packets_and_frames.frame.1.pkt_pos="2722" +packets_and_frames.frame.1.pkt_pos="2744" packets_and_frames.frame.1.pkt_size="230400" packets_and_frames.frame.1.width=320 packets_and_frames.frame.1.height=240 @@ -74,7 +74,7 @@ packets_and_frames.packet.2.dts_time="0.000000" packets_and_frames.packet.2.duration=2048 packets_and_frames.packet.2.duration_time="0.040000" packets_and_frames.packet.2.size="30000" -packets_and_frames.packet.2.pos="233143" +packets_and_frames.packet.2.pos="233165" packets_and_frames.packet.2.flags="K_" packets_and_frames.frame.2.media_type="video" packets_and_frames.frame.2.stream_index=2 @@ -87,7 +87,7 @@ packets_and_frames.frame.2.best_effort_timestamp=0 packets_and_frames.frame.2.best_effort_timestamp_time="0.000000" packets_and_frames.frame.2.pkt_duration=2048 packets_and_frames.frame.2.pkt_duration_time="0.040000" -packets_and_frames.frame.2.pkt_pos="233143" +packets_and_frames.frame.2.pkt_pos="233165" packets_and_frames.frame.2.pkt_size="30000" packets_and_frames.frame.2.width=100 packets_and_frames.frame.2.height=100 @@ -113,7 +113,7 @@ packets_and_frames.packet.3.dts_time="0.023220" packets_and_frames.packet.3.duration=1024 packets_and_frames.packet.3.duration_time="0.023220" packets_and_frames.packet.3.size="2048" -packets_and_frames.packet.3.pos="263148" +packets_and_frames.packet.3.pos="263170" packets_and_frames.packet.3.flags="K_" packets_and_frames.frame.3.media_type="audio" packets_and_frames.frame.3.stream_index=0 @@ -126,7 +126,7 @@ packets_and_frames.frame.3.best_effort_timestamp=1024 packets_and_frames.frame.3.best_effort_timestamp_time="0.023220" packets_and_frames.frame.3.pkt_duration=1024 packets_and_frames.frame.3.pkt_duration_time="0.023220" -packets_and_frames.frame.3.pkt_pos="263148" +packets_and_frames.frame.3.pkt_pos="263170" packets_and_frames.frame.3.pkt_size="2048" packets_and_frames.frame.3.sample_fmt="s16" packets_and_frames.frame.3.nb_samples=1024 @@ -141,7 +141,7 @@ packets_and_frames.packet.4.dts_time="0.040000" packets_and_frames.packet.4.duration=2048 packets_and_frames.packet.4.duration_time="0.040000" packets_and_frames.packet.4.size="230400" -packets_and_frames.packet.4.pos="265226" +packets_and_frames.packet.4.pos="265248" packets_and_frames.packet.4.flags="K_" packets_and_frames.frame.4.media_type="video" packets_and_frames.frame.4.stream_index=1 @@ -154,7 +154,7 @@ packets_and_frames.frame.4.best_effort_timestamp=2048 packets_and_frames.frame.4.best_effort_timestamp_time="0.040000" packets_and_frames.frame.4.pkt_duration=2048 packets_and_frames.frame.4.pkt_duration_time="0.040000" -packets_and_frames.frame.4.pkt_pos="265226" +packets_and_frames.frame.4.pkt_pos="265248" packets_and_frames.frame.4.pkt_size="230400" packets_and_frames.frame.4.width=320 packets_and_frames.frame.4.height=240 @@ -180,7 +180,7 @@ packets_and_frames.packet.5.dts_time="0.040000" packets_and_frames.packet.5.duration=2048 packets_and_frames.packet.5.duration_time="0.040000" packets_and_frames.packet.5.size="30000" -packets_and_frames.packet.5.pos="495650" +packets_and_frames.packet.5.pos="495672" packets_and_frames.packet.5.flags="K_" packets_and_frames.frame.5.media_type="video" packets_and_frames.frame.5.stream_index=2 @@ -193,7 +193,7 @@ packets_and_frames.frame.5.best_effort_timestamp=2048 packets_and_frames.frame.5.best_effort_timestamp_time="0.040000" packets_and_frames.frame.5.pkt_duration=2048 packets_and_frames.frame.5.pkt_duration_time="0.040000" -packets_and_frames.frame.5.pkt_pos="495650" +packets_and_frames.frame.5.pkt_pos="495672" packets_and_frames.frame.5.pkt_size="30000" packets_and_frames.frame.5.width=100 packets_and_frames.frame.5.height=100 @@ -219,7 +219,7 @@ packets_and_frames.packet.6.dts_time="0.046440" packets_and_frames.packet.6.duration=1024 packets_and_frames.packet.6.duration_time="0.023220" packets_and_frames.packet.6.size="2048" -packets_and_frames.packet.6.pos="525655" +packets_and_frames.packet.6.pos="525677" packets_and_frames.packet.6.flags="K_" packets_and_frames.frame.6.media_type="audio" packets_and_frames.frame.6.stream_index=0 @@ -232,7 +232,7 @@ packets_and_frames.frame.6.best_effort_timestamp=2048 packets_and_frames.frame.6.best_effort_timestamp_time="0.046440" packets_and_frames.frame.6.pkt_duration=1024 packets_and_frames.frame.6.pkt_duration_time="0.023220" -packets_and_frames.frame.6.pkt_pos="525655" +packets_and_frames.frame.6.pkt_pos="525677" packets_and_frames.frame.6.pkt_size="2048" packets_and_frames.frame.6.sample_fmt="s16" packets_and_frames.frame.6.nb_samples=1024 @@ -247,7 +247,7 @@ packets_and_frames.packet.7.dts_time="0.069660" packets_and_frames.packet.7.duration=1024 packets_and_frames.packet.7.duration_time="0.023220" packets_and_frames.packet.7.size="2048" -packets_and_frames.packet.7.pos="527726" +packets_and_frames.packet.7.pos="527748" packets_and_frames.packet.7.flags="K_" packets_and_frames.frame.7.media_type="audio" packets_and_frames.frame.7.stream_index=0 @@ -260,7 +260,7 @@ packets_and_frames.frame.7.best_effort_timestamp=3072 packets_and_frames.frame.7.best_effort_timestamp_time="0.069660" packets_and_frames.frame.7.pkt_duration=1024 packets_and_frames.frame.7.pkt_duration_time="0.023220" -packets_and_frames.frame.7.pkt_pos="527726" +packets_and_frames.frame.7.pkt_pos="527748" packets_and_frames.frame.7.pkt_size="2048" packets_and_frames.frame.7.sample_fmt="s16" packets_and_frames.frame.7.nb_samples=1024 @@ -275,7 +275,7 @@ packets_and_frames.packet.8.dts_time="0.080000" packets_and_frames.packet.8.duration=2048 packets_and_frames.packet.8.duration_time="0.040000" packets_and_frames.packet.8.size="230400" -packets_and_frames.packet.8.pos="529804" +packets_and_frames.packet.8.pos="529826" packets_and_frames.packet.8.flags="K_" packets_and_frames.frame.8.media_type="video" packets_and_frames.frame.8.stream_index=1 @@ -288,7 +288,7 @@ packets_and_frames.frame.8.best_effort_timestamp=4096 packets_and_frames.frame.8.best_effort_timestamp_time="0.080000" packets_and_frames.frame.8.pkt_duration=2048 packets_and_frames.frame.8.pkt_duration_time="0.040000" -packets_and_frames.frame.8.pkt_pos="529804" +packets_and_frames.frame.8.pkt_pos="529826" packets_and_frames.frame.8.pkt_size="230400" packets_and_frames.frame.8.width=320 packets_and_frames.frame.8.height=240 @@ -314,7 +314,7 @@ packets_and_frames.packet.9.dts_time="0.080000" packets_and_frames.packet.9.duration=2048 packets_and_frames.packet.9.duration_time="0.040000" packets_and_frames.packet.9.size="30000" -packets_and_frames.packet.9.pos="760228" +packets_and_frames.packet.9.pos="760250" packets_and_frames.packet.9.flags="K_" packets_and_frames.frame.9.media_type="video" packets_and_frames.frame.9.stream_index=2 @@ -327,7 +327,7 @@ packets_and_frames.frame.9.best_effort_timestamp=4096 packets_and_frames.frame.9.best_effort_timestamp_time="0.080000" packets_and_frames.frame.9.pkt_duration=2048 packets_and_frames.frame.9.pkt_duration_time="0.040000" -packets_and_frames.frame.9.pkt_pos="760228" +packets_and_frames.frame.9.pkt_pos="760250" packets_and_frames.frame.9.pkt_size="30000" packets_and_frames.frame.9.width=100 packets_and_frames.frame.9.height=100 @@ -353,7 +353,7 @@ packets_and_frames.packet.10.dts_time="0.092880" packets_and_frames.packet.10.duration=1024 packets_and_frames.packet.10.duration_time="0.023220" packets_and_frames.packet.10.size="2048" -packets_and_frames.packet.10.pos="790233" +packets_and_frames.packet.10.pos="790255" packets_and_frames.packet.10.flags="K_" packets_and_frames.frame.10.media_type="audio" packets_and_frames.frame.10.stream_index=0 @@ -366,7 +366,7 @@ packets_and_frames.frame.10.best_effort_timestamp=4096 packets_and_frames.frame.10.best_effort_timestamp_time="0.092880" packets_and_frames.frame.10.pkt_duration=1024 packets_and_frames.frame.10.pkt_duration_time="0.023220" -packets_and_frames.frame.10.pkt_pos="790233" +packets_and_frames.frame.10.pkt_pos="790255" packets_and_frames.frame.10.pkt_size="2048" packets_and_frames.frame.10.sample_fmt="s16" packets_and_frames.frame.10.nb_samples=1024 @@ -381,7 +381,7 @@ packets_and_frames.packet.11.dts_time="0.116100" packets_and_frames.packet.11.duration=393 packets_and_frames.packet.11.duration_time="0.008912" packets_and_frames.packet.11.size="786" -packets_and_frames.packet.11.pos="792304" +packets_and_frames.packet.11.pos="792326" packets_and_frames.packet.11.flags="K_" packets_and_frames.frame.11.media_type="audio" packets_and_frames.frame.11.stream_index=0 @@ -394,7 +394,7 @@ packets_and_frames.frame.11.best_effort_timestamp=5120 packets_and_frames.frame.11.best_effort_timestamp_time="0.116100" packets_and_frames.frame.11.pkt_duration=393 packets_and_frames.frame.11.pkt_duration_time="0.008912" -packets_and_frames.frame.11.pkt_pos="792304" +packets_and_frames.frame.11.pkt_pos="792326" packets_and_frames.frame.11.pkt_size="786" packets_and_frames.frame.11.sample_fmt="s16" packets_and_frames.frame.11.nb_samples=393 @@ -409,7 +409,7 @@ packets_and_frames.packet.12.dts_time="0.120000" packets_and_frames.packet.12.duration=2048 packets_and_frames.packet.12.duration_time="0.040000" packets_and_frames.packet.12.size="230400" -packets_and_frames.packet.12.pos="793120" +packets_and_frames.packet.12.pos="793142" packets_and_frames.packet.12.flags="K_" packets_and_frames.frame.12.media_type="video" packets_and_frames.frame.12.stream_index=1 @@ -422,7 +422,7 @@ packets_and_frames.frame.12.best_effort_timestamp=6144 packets_and_frames.frame.12.best_effort_timestamp_time="0.120000" packets_and_frames.frame.12.pkt_duration=2048 packets_and_frames.frame.12.pkt_duration_time="0.040000" -packets_and_frames.frame.12.pkt_pos="793120" +packets_and_frames.frame.12.pkt_pos="793142" packets_and_frames.frame.12.pkt_size="230400" packets_and_frames.frame.12.width=320 packets_and_frames.frame.12.height=240 @@ -448,7 +448,7 @@ packets_and_frames.packet.13.dts_time="0.120000" packets_and_frames.packet.13.duration=2048 packets_and_frames.packet.13.duration_time="0.040000" packets_and_frames.packet.13.size="30000" -packets_and_frames.packet.13.pos="1023544" +packets_and_frames.packet.13.pos="1023566" packets_and_frames.packet.13.flags="K_" packets_and_frames.frame.13.media_type="video" packets_and_frames.frame.13.stream_index=2 @@ -461,7 +461,7 @@ packets_and_frames.frame.13.best_effort_timestamp=6144 packets_and_frames.frame.13.best_effort_timestamp_time="0.120000" packets_and_frames.frame.13.pkt_duration=2048 packets_and_frames.frame.13.pkt_duration_time="0.040000" -packets_and_frames.frame.13.pkt_pos="1023544" +packets_and_frames.frame.13.pkt_pos="1023566" packets_and_frames.frame.13.pkt_size="30000" packets_and_frames.frame.13.width=100 packets_and_frames.frame.13.height=100 @@ -560,7 +560,7 @@ streams.stream.1.bits_per_raw_sample="N/A" streams.stream.1.nb_frames="N/A" streams.stream.1.nb_read_frames="4" streams.stream.1.nb_read_packets="4" -streams.stream.1.disposition.default=0 +streams.stream.1.disposition.default=1 streams.stream.1.disposition.dub=0 streams.stream.1.disposition.original=0 streams.stream.1.disposition.comment=0 @@ -642,8 +642,8 @@ format.nb_programs=0 format.format_name="nut" format.start_time="0.000000" format.duration="0.120000" -format.size="1053624" -format.bit_rate="70241600" +format.size="1053646" +format.bit_rate="70243066" format.probe_score=100 format.tags.title="ffprobe test file" format.tags.comment="'A comment with CSV, XML & JSON special chars': " diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini index f64c4e891d..cff7d96003 100644 --- a/tests/ref/fate/ffprobe_ini +++ b/tests/ref/fate/ffprobe_ini @@ -10,7 +10,7 @@ dts_time=0.000000 duration=1024 duration_time=0.023220 size=2048 -pos=647 +pos=669 flags=K_ [packets_and_frames.frame.0] @@ -25,7 +25,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=647 +pkt_pos=669 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -42,7 +42,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=230400 -pos=2722 +pos=2744 flags=K_ [packets_and_frames.frame.1] @@ -57,7 +57,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=2722 +pkt_pos=2744 pkt_size=230400 width=320 height=240 @@ -85,7 +85,7 @@ dts_time=0.000000 duration=2048 duration_time=0.040000 size=30000 -pos=233143 +pos=233165 flags=K_ [packets_and_frames.frame.2] @@ -100,7 +100,7 @@ best_effort_timestamp=0 best_effort_timestamp_time=0.000000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=233143 +pkt_pos=233165 pkt_size=30000 width=100 height=100 @@ -128,7 +128,7 @@ dts_time=0.023220 duration=1024 duration_time=0.023220 size=2048 -pos=263148 +pos=263170 flags=K_ [packets_and_frames.frame.3] @@ -143,7 +143,7 @@ best_effort_timestamp=1024 best_effort_timestamp_time=0.023220 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=263148 +pkt_pos=263170 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -160,7 +160,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=230400 -pos=265226 +pos=265248 flags=K_ [packets_and_frames.frame.4] @@ -175,7 +175,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=265226 +pkt_pos=265248 pkt_size=230400 width=320 height=240 @@ -203,7 +203,7 @@ dts_time=0.040000 duration=2048 duration_time=0.040000 size=30000 -pos=495650 +pos=495672 flags=K_ [packets_and_frames.frame.5] @@ -218,7 +218,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.040000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=495650 +pkt_pos=495672 pkt_size=30000 width=100 height=100 @@ -246,7 +246,7 @@ dts_time=0.046440 duration=1024 duration_time=0.023220 size=2048 -pos=525655 +pos=525677 flags=K_ [packets_and_frames.frame.6] @@ -261,7 +261,7 @@ best_effort_timestamp=2048 best_effort_timestamp_time=0.046440 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=525655 +pkt_pos=525677 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -278,7 +278,7 @@ dts_time=0.069660 duration=1024 duration_time=0.023220 size=2048 -pos=527726 +pos=527748 flags=K_ [packets_and_frames.frame.7] @@ -293,7 +293,7 @@ best_effort_timestamp=3072 best_effort_timestamp_time=0.069660 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=527726 +pkt_pos=527748 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -310,7 +310,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=230400 -pos=529804 +pos=529826 flags=K_ [packets_and_frames.frame.8] @@ -325,7 +325,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=529804 +pkt_pos=529826 pkt_size=230400 width=320 height=240 @@ -353,7 +353,7 @@ dts_time=0.080000 duration=2048 duration_time=0.040000 size=30000 -pos=760228 +pos=760250 flags=K_ [packets_and_frames.frame.9] @@ -368,7 +368,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.080000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=760228 +pkt_pos=760250 pkt_size=30000 width=100 height=100 @@ -396,7 +396,7 @@ dts_time=0.092880 duration=1024 duration_time=0.023220 size=2048 -pos=790233 +pos=790255 flags=K_ [packets_and_frames.frame.10] @@ -411,7 +411,7 @@ best_effort_timestamp=4096 best_effort_timestamp_time=0.092880 pkt_duration=1024 pkt_duration_time=0.023220 -pkt_pos=790233 +pkt_pos=790255 pkt_size=2048 sample_fmt=s16 nb_samples=1024 @@ -428,7 +428,7 @@ dts_time=0.116100 duration=393 duration_time=0.008912 size=786 -pos=792304 +pos=792326 flags=K_ [packets_and_frames.frame.11] @@ -443,7 +443,7 @@ best_effort_timestamp=5120 best_effort_timestamp_time=0.116100 pkt_duration=393 pkt_duration_time=0.008912 -pkt_pos=792304 +pkt_pos=792326 pkt_size=786 sample_fmt=s16 nb_samples=393 @@ -460,7 +460,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=230400 -pos=793120 +pos=793142 flags=K_ [packets_and_frames.frame.12] @@ -475,7 +475,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=793120 +pkt_pos=793142 pkt_size=230400 width=320 height=240 @@ -503,7 +503,7 @@ dts_time=0.120000 duration=2048 duration_time=0.040000 size=30000 -pos=1023544 +pos=1023566 flags=K_ [packets_and_frames.frame.13] @@ -518,7 +518,7 @@ best_effort_timestamp=6144 best_effort_timestamp_time=0.120000 pkt_duration=2048 pkt_duration_time=0.040000 -pkt_pos=1023544 +pkt_pos=1023566 pkt_size=30000 width=100 height=100 @@ -627,7 +627,7 @@ nb_read_frames=4 nb_read_packets=4 [streams.stream.1.disposition] -default=0 +default=1 dub=0 original=0 comment=0 @@ -719,8 +719,8 @@ nb_programs=0 format_name=nut start_time=0.000000 duration=0.120000 -size=1053624 -bit_rate=70241600 +size=1053646 +bit_rate=70243066 probe_score=100 [format.tags] diff --git a/tests/ref/fate/ffprobe_json b/tests/ref/fate/ffprobe_json index a94776030b..9816700b53 100644 --- a/tests/ref/fate/ffprobe_json +++ b/tests/ref/fate/ffprobe_json @@ -11,7 +11,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "647", + "pos": "669", "flags": "K_" }, { @@ -27,7 +27,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "647", + "pkt_pos": "669", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -44,7 +44,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "2722", + "pos": "2744", "flags": "K_" }, { @@ -60,7 +60,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "2722", + "pkt_pos": "2744", "pkt_size": "230400", "width": 320, "height": 240, @@ -84,7 +84,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "233143", + "pos": "233165", "flags": "K_" }, { @@ -100,7 +100,7 @@ "best_effort_timestamp_time": "0.000000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "233143", + "pkt_pos": "233165", "pkt_size": "30000", "width": 100, "height": 100, @@ -124,7 +124,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "263148", + "pos": "263170", "flags": "K_" }, { @@ -140,7 +140,7 @@ "best_effort_timestamp_time": "0.023220", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "263148", + "pkt_pos": "263170", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -157,7 +157,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "265226", + "pos": "265248", "flags": "K_" }, { @@ -173,7 +173,7 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "265226", + "pkt_pos": "265248", "pkt_size": "230400", "width": 320, "height": 240, @@ -197,7 +197,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "495650", + "pos": "495672", "flags": "K_" }, { @@ -213,7 +213,7 @@ "best_effort_timestamp_time": "0.040000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "495650", + "pkt_pos": "495672", "pkt_size": "30000", "width": 100, "height": 100, @@ -237,7 +237,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "525655", + "pos": "525677", "flags": "K_" }, { @@ -253,7 +253,7 @@ "best_effort_timestamp_time": "0.046440", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "525655", + "pkt_pos": "525677", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -270,7 +270,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "527726", + "pos": "527748", "flags": "K_" }, { @@ -286,7 +286,7 @@ "best_effort_timestamp_time": "0.069660", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "527726", + "pkt_pos": "527748", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -303,7 +303,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "529804", + "pos": "529826", "flags": "K_" }, { @@ -319,7 +319,7 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "529804", + "pkt_pos": "529826", "pkt_size": "230400", "width": 320, "height": 240, @@ -343,7 +343,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "760228", + "pos": "760250", "flags": "K_" }, { @@ -359,7 +359,7 @@ "best_effort_timestamp_time": "0.080000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "760228", + "pkt_pos": "760250", "pkt_size": "30000", "width": 100, "height": 100, @@ -383,7 +383,7 @@ "duration": 1024, "duration_time": "0.023220", "size": "2048", - "pos": "790233", + "pos": "790255", "flags": "K_" }, { @@ -399,7 +399,7 @@ "best_effort_timestamp_time": "0.092880", "pkt_duration": 1024, "pkt_duration_time": "0.023220", - "pkt_pos": "790233", + "pkt_pos": "790255", "pkt_size": "2048", "sample_fmt": "s16", "nb_samples": 1024, @@ -416,7 +416,7 @@ "duration": 393, "duration_time": "0.008912", "size": "786", - "pos": "792304", + "pos": "792326", "flags": "K_" }, { @@ -432,7 +432,7 @@ "best_effort_timestamp_time": "0.116100", "pkt_duration": 393, "pkt_duration_time": "0.008912", - "pkt_pos": "792304", + "pkt_pos": "792326", "pkt_size": "786", "sample_fmt": "s16", "nb_samples": 393, @@ -449,7 +449,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "230400", - "pos": "793120", + "pos": "793142", "flags": "K_" }, { @@ -465,7 +465,7 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "793120", + "pkt_pos": "793142", "pkt_size": "230400", "width": 320, "height": 240, @@ -489,7 +489,7 @@ "duration": 2048, "duration_time": "0.040000", "size": "30000", - "pos": "1023544", + "pos": "1023566", "flags": "K_" }, { @@ -505,7 +505,7 @@ "best_effort_timestamp_time": "0.120000", "pkt_duration": 2048, "pkt_duration_time": "0.040000", - "pkt_pos": "1023544", + "pkt_pos": "1023566", "pkt_size": "30000", "width": 100, "height": 100, @@ -588,7 +588,7 @@ "nb_read_frames": "4", "nb_read_packets": "4", "disposition": { - "default": 0, + "default": 1, "dub": 0, "original": 0, "comment": 0, @@ -668,8 +668,8 @@ "format_name": "nut", "start_time": "0.000000", "duration": "0.120000", - "size": "1053624", - "bit_rate": "70241600", + "size": "1053646", + "bit_rate": "70243066", "probe_score": 100, "tags": { "title": "ffprobe test file", diff --git a/tests/ref/fate/ffprobe_xml b/tests/ref/fate/ffprobe_xml index 88623f0e11..4f702bc984 100644 --- a/tests/ref/fate/ffprobe_xml +++ b/tests/ref/fate/ffprobe_xml @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38,7 +38,7 @@ - + @@ -49,7 +49,7 @@ - + diff --git a/tests/ref/fate/ffprobe_xsd b/tests/ref/fate/ffprobe_xsd index c4a6bf86d2..62d011ad9c 100644 --- a/tests/ref/fate/ffprobe_xsd +++ b/tests/ref/fate/ffprobe_xsd @@ -1,34 +1,34 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -38,7 +38,7 @@ - + @@ -49,7 +49,7 @@ - + diff --git a/tests/ref/fate/fifo b/tests/ref/fate/fifo index 2b18ed5ffc..1b0e005412 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-negate b/tests/ref/fate/filter-negate index 88d04718ae..aa9a820c0d 100644 --- a/tests/ref/fate/filter-negate +++ b/tests/ref/fate/filter-negate @@ -3,53 +3,53 @@ #codec_id 0: rawvideo #dimensions 0: 352x288 #sar 0: 0/1 -0, 0, 0, 1, 152064, 0xef20e1ec -0, 1, 1, 1, 152064, 0x899606ec -0, 2, 2, 1, 152064, 0xaea175d2 -0, 3, 3, 1, 152064, 0x5201eb55 -0, 4, 4, 1, 152064, 0xf02bb525 -0, 5, 5, 1, 152064, 0x99fdc305 -0, 6, 6, 1, 152064, 0x3a8fefe7 -0, 7, 7, 1, 152064, 0x005edfbf -0, 8, 8, 1, 152064, 0xe37aea50 -0, 9, 9, 1, 152064, 0xa5ad32f9 -0, 10, 10, 1, 152064, 0xb1e52485 -0, 11, 11, 1, 152064, 0x55b06e56 -0, 12, 12, 1, 152064, 0xdfb7be97 -0, 13, 13, 1, 152064, 0x191bca13 -0, 14, 14, 1, 152064, 0xa554dd3c -0, 15, 15, 1, 152064, 0x36075b77 -0, 16, 16, 1, 152064, 0xbf6b1cbd -0, 17, 17, 1, 152064, 0xf33432b6 -0, 18, 18, 1, 152064, 0x5d7100c3 -0, 19, 19, 1, 152064, 0x376f8f0c -0, 20, 20, 1, 152064, 0x07ca75fa -0, 21, 21, 1, 152064, 0xe3984704 -0, 22, 22, 1, 152064, 0xa8fb4e4c -0, 23, 23, 1, 152064, 0xe8e102d8 -0, 24, 24, 1, 152064, 0xcc6771c9 -0, 25, 25, 1, 152064, 0xf646d238 -0, 26, 26, 1, 152064, 0xa52cd41e -0, 27, 27, 1, 152064, 0x536d92c2 -0, 28, 28, 1, 152064, 0x7058c6a1 -0, 29, 29, 1, 152064, 0xcc6c05d0 -0, 30, 30, 1, 152064, 0x1fc2ffb8 -0, 31, 31, 1, 152064, 0x041ea59c -0, 32, 32, 1, 152064, 0xfc006e07 -0, 33, 33, 1, 152064, 0x0246efe1 -0, 34, 34, 1, 152064, 0x079428e5 -0, 35, 35, 1, 152064, 0x64d9d773 -0, 36, 36, 1, 152064, 0x914d3454 -0, 37, 37, 1, 152064, 0xef69686e -0, 38, 38, 1, 152064, 0x3c91129f -0, 39, 39, 1, 152064, 0x2a611ca7 -0, 40, 40, 1, 152064, 0xaf56124f -0, 41, 41, 1, 152064, 0xce48cd45 -0, 42, 42, 1, 152064, 0x75feac29 -0, 43, 43, 1, 152064, 0xfd2b4b5b -0, 44, 44, 1, 152064, 0x8d2f675c -0, 45, 45, 1, 152064, 0x1573ed3b -0, 46, 46, 1, 152064, 0xb0fc17ca -0, 47, 47, 1, 152064, 0x53e5a654 -0, 48, 48, 1, 152064, 0xe0cbb786 -0, 49, 49, 1, 152064, 0xcaa092fe +0, 0, 0, 1, 152064, 0xdb0946b2 +0, 1, 1, 1, 152064, 0x950c6b50 +0, 2, 2, 1, 152064, 0x42e3da48 +0, 3, 3, 1, 152064, 0xb63d4ff1 +0, 4, 4, 1, 152064, 0x92dd1a4f +0, 5, 5, 1, 152064, 0xf2fc27bb +0, 6, 6, 1, 152064, 0xfea2547e +0, 7, 7, 1, 152064, 0x860b44f5 +0, 8, 8, 1, 152064, 0xc1a5507b +0, 9, 9, 1, 152064, 0x4f89978c +0, 10, 10, 1, 152064, 0xde8c8941 +0, 11, 11, 1, 152064, 0xafcbd3bd +0, 12, 12, 1, 152064, 0x19af2340 +0, 13, 13, 1, 152064, 0xbbd42e7e +0, 14, 14, 1, 152064, 0x8e1c42c4 +0, 15, 15, 1, 152064, 0x37a4c19c +0, 16, 16, 1, 152064, 0x528a8289 +0, 17, 17, 1, 152064, 0x2f6397d9 +0, 18, 18, 1, 152064, 0xee5265d5 +0, 19, 19, 1, 152064, 0xed64f493 +0, 20, 20, 1, 152064, 0xe436db22 +0, 21, 21, 1, 152064, 0x42f9ac8f +0, 22, 22, 1, 152064, 0x9c63b348 +0, 23, 23, 1, 152064, 0xb19967b2 +0, 24, 24, 1, 152064, 0x12b7d6bc +0, 25, 25, 1, 152064, 0x4b69376b +0, 26, 26, 1, 152064, 0x9ce939ec +0, 27, 27, 1, 152064, 0x0940f80b +0, 28, 28, 1, 152064, 0x69ee2c4c +0, 29, 29, 1, 152064, 0x72fd6b93 +0, 30, 30, 1, 152064, 0xd12365d7 +0, 31, 31, 1, 152064, 0xfe1c0b83 +0, 32, 32, 1, 152064, 0x095ad405 +0, 33, 33, 1, 152064, 0xfe825671 +0, 34, 34, 1, 152064, 0x60d68d29 +0, 35, 35, 1, 152064, 0xe6243ba6 +0, 36, 36, 1, 152064, 0x942998f6 +0, 37, 37, 1, 152064, 0x3bb3cea9 +0, 38, 38, 1, 152064, 0xd5b97755 +0, 39, 39, 1, 152064, 0x584d81c4 +0, 40, 40, 1, 152064, 0x0e4d777c +0, 41, 41, 1, 152064, 0x0bdc3299 +0, 42, 42, 1, 152064, 0xbff210f8 +0, 43, 43, 1, 152064, 0x8964afb5 +0, 44, 44, 1, 152064, 0xe361cc30 +0, 45, 45, 1, 152064, 0x7f0c522e +0, 46, 46, 1, 152064, 0xd6d17ca2 +0, 47, 47, 1, 152064, 0x72380adf +0, 48, 48, 1, 152064, 0x25391c1e +0, 49, 49, 1, 152064, 0x9506f7a8 diff --git a/tests/ref/fate/filter-pixdesc-p210be b/tests/ref/fate/filter-pixdesc-p210be new file mode 100644 index 0000000000..9ff89d14a0 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p210be @@ -0,0 +1 @@ +pixdesc-p210be 016fd90989d14914bbbcc7dc2968bef0 diff --git a/tests/ref/fate/filter-pixdesc-p210le b/tests/ref/fate/filter-pixdesc-p210le new file mode 100644 index 0000000000..cdb96e9cf5 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p210le @@ -0,0 +1 @@ +pixdesc-p210le 9994fb3da38c83d3b5fd4994993ad0ae diff --git a/tests/ref/fate/filter-pixdesc-p216be b/tests/ref/fate/filter-pixdesc-p216be new file mode 100644 index 0000000000..932c5b2708 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p216be @@ -0,0 +1 @@ +pixdesc-p216be d95084fa0758169851f57455a9624a2e diff --git a/tests/ref/fate/filter-pixdesc-p216le b/tests/ref/fate/filter-pixdesc-p216le new file mode 100644 index 0000000000..5ade1ee75f --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p216le @@ -0,0 +1 @@ +pixdesc-p216le 79d711ee3dac99e37c013d2073d90a2c diff --git a/tests/ref/fate/filter-pixdesc-p410be b/tests/ref/fate/filter-pixdesc-p410be new file mode 100644 index 0000000000..27de3ee0bb --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p410be @@ -0,0 +1 @@ +pixdesc-p410be 33d7e8e5d6a85cc22fcbf0c12c7bafd0 diff --git a/tests/ref/fate/filter-pixdesc-p410le b/tests/ref/fate/filter-pixdesc-p410le new file mode 100644 index 0000000000..826d98ea5e --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p410le @@ -0,0 +1 @@ +pixdesc-p410le 0b90a10af76240042876793a1dafa862 diff --git a/tests/ref/fate/filter-pixdesc-p416be b/tests/ref/fate/filter-pixdesc-p416be new file mode 100644 index 0000000000..f67b553d42 --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p416be @@ -0,0 +1 @@ +pixdesc-p416be 6a4b1b2fc8435acfc82312109f13bc58 diff --git a/tests/ref/fate/filter-pixdesc-p416le b/tests/ref/fate/filter-pixdesc-p416le new file mode 100644 index 0000000000..25e733b69d --- /dev/null +++ b/tests/ref/fate/filter-pixdesc-p416le @@ -0,0 +1 @@ +pixdesc-p416le e0f93774f62dd3b261fb8637696f3773 diff --git a/tests/ref/fate/filter-pixfmts-copy b/tests/ref/fate/filter-pixfmts-copy index 790b733112..f06fa1574e 100644 --- a/tests/ref/fate/filter-pixfmts-copy +++ b/tests/ref/fate/filter-pixfmts-copy @@ -63,6 +63,14 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b +p210be 847e9c6e292b17349e69570829252b3e +p210le c06e4b76cf504e908128081f92b60ce2 +p216be f5009974fc1cd5d552705eeb52de35d9 +p216le 2f634e1a3cd5c9c122e0f2ebadb3503d +p410be 7c2509d2df4bbb199ab653ebb6dce61e +p410le 527761e1f4381007044679710a352ecc +p416be fd828e966d45ae908f5d2d4b3349b816 +p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-crop b/tests/ref/fate/filter-pixfmts-crop index 3c410cbd6b..8b26ab9c53 100644 --- a/tests/ref/fate/filter-pixfmts-crop +++ b/tests/ref/fate/filter-pixfmts-crop @@ -61,6 +61,14 @@ p010be 8b2de2eb6b099bbf355bfc55a0694ddc p010le 373b50c766dfd0a8e79c9a73246d803a p016be 8b2de2eb6b099bbf355bfc55a0694ddc p016le 373b50c766dfd0a8e79c9a73246d803a +p210be 2947f43774352ef61f9e83777548c7c5 +p210le 74fcd5a32eee687eebe002c884103963 +p216be 41351128eaf636041c8987698730391a +p216le e56f5e5b0d4460d56f27a5df8a4a1462 +p410be e17c78ff059363177548412e6ab4e65f +p410le 75f910c7282d8065d97f502ba974c481 +p416be 52f08b8a56a09d6e954c2eab6cf24d99 +p416le ecb78b327ea5cfe1fff82945c1fca310 pal8 1f2cdc8e718f95c875dbc1034a688bfb rgb0 736646b70dd9a0be22b8da8041e35035 rgb24 c5fbbf816bb2000f4d2914e335698ef5 diff --git a/tests/ref/fate/filter-pixfmts-field b/tests/ref/fate/filter-pixfmts-field index 37718d81d0..c4838d1446 100644 --- a/tests/ref/fate/filter-pixfmts-field +++ b/tests/ref/fate/filter-pixfmts-field @@ -63,6 +63,14 @@ p010be a0311a09bba7383553267d2b3b9c075e p010le ee09a18aefa3ebe97715b3a7312cb8ff p016be a0311a09bba7383553267d2b3b9c075e p016le ee09a18aefa3ebe97715b3a7312cb8ff +p210be 58d46f566ab28e3bcfb715c7aa53cf58 +p210le 8d68f7655a3d76f2f8436bd25beb3973 +p216be dd1f3e0bb5c49775a598ab29802fc268 +p216le b573c0473a1368813d077487cc9bce0e +p410be 658fd0d92eb327cbd562abafc8694db7 +p410le c981188c7fd9f32988a9f4732303f82b +p416be 66616bf2320464b5e9b6372d48b6b9a9 +p416le 1039b97bbe42ef0af1bc46d2c0fc819e pal8 0658c18dcd8d052d59dfbe23f5b368d9 rgb0 ca3fa6e865b91b3511c7f2bf62830059 rgb24 25ab271e26a5785be169578d99da5dd0 diff --git a/tests/ref/fate/filter-pixfmts-fieldorder b/tests/ref/fate/filter-pixfmts-fieldorder index 88780c05a7..32c06bae4c 100644 --- a/tests/ref/fate/filter-pixfmts-fieldorder +++ b/tests/ref/fate/filter-pixfmts-fieldorder @@ -55,6 +55,14 @@ grayf32be 1aa7960131f880c54fe3c77f13448674 grayf32le 4029ac9d197f255794c1b9e416520fc7 nv24 4fdbef26042c77f012df114e666efdb2 nv42 59608290fece913e6b7d61edf581a529 +p210be ca2ce2c25db43dcd14729b2a72a7c604 +p210le 755363012d8801b96ead2e8b1b4d2ab8 +p216be 17741c0cdb65914ad13c5114121a175f +p216le c0c888ab7bde56638732344076b3b2ba +p410be b6d65b820198ca6ff0103d9794727792 +p410le 2771dd3ae54a439921f51c29e79b6799 +p416be a0f8b5acad8fafc45fc7b2275fac1d84 +p416le 2e73af44eb933580da59981176848dcc rgb0 2e3d8c91c7a83d451593dfd06607ff39 rgb24 b82577f8215d3dc2681be60f1da247af rgb444be 1c3afc3a0c53c51139c76504f59bb1f4 diff --git a/tests/ref/fate/filter-pixfmts-hflip b/tests/ref/fate/filter-pixfmts-hflip index 69c7b42b6e..4d3efe3cdc 100644 --- a/tests/ref/fate/filter-pixfmts-hflip +++ b/tests/ref/fate/filter-pixfmts-hflip @@ -61,6 +61,14 @@ p010be 744b13e44d39e1ff7588983fa03e0101 p010le a50b160346ab94f55a425065b57006f0 p016be 744b13e44d39e1ff7588983fa03e0101 p016le a50b160346ab94f55a425065b57006f0 +p210be 6f5a76d6467b86d55fe5589d3af8a7ea +p210le b6982912b2376371edea4fccf99fe40c +p216be c1b58f61cd6df9cf01c3086786fb8a69 +p216le 1f5213bebf4c99634f57290f5ad99c0d +p410be 2e06214ea84595aa1294239b0f1e900f +p410le 1143c811c383e4461b1192dca0c74246 +p416be da6807d924b63a54b804d32e427524bf +p416le a42b88cabc4395aa0bf1bcbbc876f48f pal8 5b7c77d99817b4f52339742a47de7797 rgb0 0092452f37d73da20193265ace0b7d57 rgb24 21571104e6091a689feabb7867e513dd diff --git a/tests/ref/fate/filter-pixfmts-il b/tests/ref/fate/filter-pixfmts-il index 09fe072314..4623f2420c 100644 --- a/tests/ref/fate/filter-pixfmts-il +++ b/tests/ref/fate/filter-pixfmts-il @@ -63,6 +63,14 @@ p010be 3df51286ef66b53e3e283dbbab582263 p010le eadcd8241e97e35b2b47d5eb2eaea6cd p016be 3df51286ef66b53e3e283dbbab582263 p016le eadcd8241e97e35b2b47d5eb2eaea6cd +p210be 29ec4e8912d456cd15203a96487c42e8 +p210le c695064fb9f2cc4e35957d4d649cc281 +p216be ad85bdc59755608602608a9438bb82ea +p216le 77757390da383a90981e461d128d8789 +p410be 2128861337e660232e6fb664cc4de3e6 +p410le 6cf3a3e199b327f4f013e0346410d7a8 +p416be 47dec75cefeb6220be7731bc25b7be9c +p416le 4990b51ff889d9ee23e68997f81c09f1 rgb0 cfaf68671e43248267d8cd50cae8c13f rgb24 88894f608cf33ba310f21996748d77a7 rgb444be 99d36d814988fb388aacdef575dacfcf diff --git a/tests/ref/fate/filter-pixfmts-null b/tests/ref/fate/filter-pixfmts-null index 790b733112..f06fa1574e 100644 --- a/tests/ref/fate/filter-pixfmts-null +++ b/tests/ref/fate/filter-pixfmts-null @@ -63,6 +63,14 @@ p010be 7f9842d6015026136bad60d03c035cc3 p010le c453421b9f726bdaf2bacf59a492c43b p016be 7f9842d6015026136bad60d03c035cc3 p016le c453421b9f726bdaf2bacf59a492c43b +p210be 847e9c6e292b17349e69570829252b3e +p210le c06e4b76cf504e908128081f92b60ce2 +p216be f5009974fc1cd5d552705eeb52de35d9 +p216le 2f634e1a3cd5c9c122e0f2ebadb3503d +p410be 7c2509d2df4bbb199ab653ebb6dce61e +p410le 527761e1f4381007044679710a352ecc +p416be fd828e966d45ae908f5d2d4b3349b816 +p416le 983064bfd506be1e26cd57bafc14ae50 pal8 ff5929f5b42075793b2c34cb441bede5 rgb0 0de71e5a1f97f81fb51397a0435bfa72 rgb24 f4438057d046e6d98ade4e45294b21be diff --git a/tests/ref/fate/filter-pixfmts-pad b/tests/ref/fate/filter-pixfmts-pad index 57fa817cf5..519473032e 100644 --- a/tests/ref/fate/filter-pixfmts-pad +++ b/tests/ref/fate/filter-pixfmts-pad @@ -1,8 +1,8 @@ -0bgr 7bc6f5a1c44cdd7506174dccf52c68d7 -0rgb ff12e0f1e576b47a4c962729d5c0b868 +0bgr 55d41bba3609383bf658169f90b30b42 +0rgb 8e076dd0f8a9f4652595dffe3544f0f0 abgr 52738042432893de555e6a3833172806 argb 2a10108ac524b422b8a2393c064b3eab -bgr0 32207a2de1b2ac7937e940a8459b97c0 +bgr0 025d4d5e5691801ba39bc9de70e39df0 bgr24 f8b65ad845905c7d0c93ca28dfbb826f bgra 929aac15e848038e367c250037575f9f gbrap 5f16cccab5a17cb766c882e865995167 @@ -25,14 +25,18 @@ nv12 381574979cb04be10c9168540310afad nv21 0fdeb2cdd56cf5a7147dc273456fa217 nv24 193b9eadcc06ad5081609f76249b3e47 nv42 1738ad3c31c6c16e17679f5b09ce4677 -rgb0 78d500c8361ab6423a4826a00268c908 +p010le c57224f2dc09601c66aa3365b3cd7254 +p016le c57224f2dc09601c66aa3365b3cd7254 +p210le abc02945a9b9585f0914716e4787cefb +p216le 1b43feb94b8a030c0c699aa0deff017b +p410le 1f0294141ae1657d6c10c6a0d46a879f +p416le 320e558b7ee8d598231ae0763ecca275 +rgb0 0984eb985dabbe757ed6beb53db84eff rgb24 17f9e2e0c609009acaf2175c42d4a2a5 rgba b157c90191463d34fb3ce77b36c96386 -x2bgr10le d4aff89f5e15ccbb1812f319874ed444 -x2rgb10le a0c5925bd56b6f85f918c4e9fb93e90e xyz12le 85abf80b77a9236a76ba0b00fcbdea2d -ya16le 940fafa240b9916de5f73cb20a552f24 -ya8 5fc0f471207ddf7aa01b07027d56b672 +ya16le d85740ba2cac9fa9ea8aaea8a5864407 +ya8 495daaca2dcb4f7aeba7652768b41ced yuv410p cb871dcc1e84a7ef1d21f9237b88cf6e yuv411p aec2c1740de9a62db0d41f4dda9121b0 yuv420p 4398e408fc35436ce4b20468946f58b6 diff --git a/tests/ref/fate/filter-pixfmts-scale b/tests/ref/fate/filter-pixfmts-scale index 07c4ff536d..43074b84a7 100644 --- a/tests/ref/fate/filter-pixfmts-scale +++ b/tests/ref/fate/filter-pixfmts-scale @@ -19,9 +19,9 @@ bgra d8316272bc3a360ef9dff3ecc84520a3 bgra64be 4e6a1b9f9c18b881c27d76611d45f737 bgra64le efeee0abcc658ebcff049d5e74d74943 gbrap 4a100f750ac846b34bfeef0d6893c3de -gbrap10be dc6aea3559ea4fcdda1ccc4f23d2f2fb +gbrap10be 50735fbc471a5ac5a6645c85881f3670 gbrap10le 6e1cba57029fdf0f9d46b5e5cd55112b -gbrap12be dbe3a662c016563529032cd4dfb80262 +gbrap12be 58170165829484b3db4a3b9165198987 gbrap12le 24f5ecb32435b73353517e017c165e31 gbrap16be 31968e6872a46e8174fb57f8920ed10d gbrap16le 8c6758f33671b673b6d30969fc05a23d @@ -63,6 +63,14 @@ p010be 1d6726d94bf1385996a9a9840dd0e878 p010le 4b316f2b9e18972299beb73511278fa8 p016be 31e204018cbb53f8988c4e1174ea8ce9 p016le d5afe557f492a09317e525d7cb782f5b +p210be 2cc6dfcf5e006c8ed5238988a06fd45e +p210le 04efb8f14a9d98417af40954a06aa187 +p216be 2f649a226812c8e5a553c4e22d301684 +p216le c8f65811f717a12706a598561c6df46d +p410be 354cd1324ad382df1a3d573833323cce +p410le 90fdd95ec4482c127d98307550a885c6 +p416be aa54294859a8e6cb2c9cf64d343fdb60 +p416le d91a0858ea8d2cf1ed29f179c9ad9666 pal8 29e10892009b2cfe431815ec3052ed3b rgb0 fbd27e98154efb7535826afed41e9bb0 rgb24 e022e741451e81f2ecce1c7240b93e87 diff --git a/tests/ref/fate/filter-pixfmts-transpose b/tests/ref/fate/filter-pixfmts-transpose index 5117bcf763..922666cf95 100644 --- a/tests/ref/fate/filter-pixfmts-transpose +++ b/tests/ref/fate/filter-pixfmts-transpose @@ -61,6 +61,10 @@ p010be ad0de2cc9bff81688b182a870fcf7000 p010le e7ff5143595021246733ce6bd0a769e8 p016be ad0de2cc9bff81688b182a870fcf7000 p016le e7ff5143595021246733ce6bd0a769e8 +p410be 8b3e0ccb31b6a20ff00a29253fb2dec3 +p410le 4e5f78dfccda9a6387e81354a56a033a +p416be 350a90bda53349435d89ec13533726b7 +p416le 7bb46e2aec65669a27502ec452941237 rgb0 31ea5da7fe779c6ea0a33f1d28aad918 rgb24 47654cabaaad79170b90afd5a02161dd rgb444be 3cac1f0c43a74d2a95eb02e187070845 diff --git a/tests/ref/fate/filter-pixfmts-vflip b/tests/ref/fate/filter-pixfmts-vflip index 34c1a9c64f..3a53bb5837 100644 --- a/tests/ref/fate/filter-pixfmts-vflip +++ b/tests/ref/fate/filter-pixfmts-vflip @@ -63,6 +63,14 @@ p010be 06e9354b6e0e38ba41736352cedc0bd5 p010le fd18d322bffbf5816902c13102872e22 p016be 06e9354b6e0e38ba41736352cedc0bd5 p016le fd18d322bffbf5816902c13102872e22 +p210be ca886ab2b3ea5c153f1954b3709f7249 +p210le d71c2d4e483030ffd87fa6a68c83fce0 +p216be 7f268f755ed02592b3a49fd5f7bd48bb +p216le 2c0a660762527706799c4705ca50a9c5 +p410be 4c603e4464ed3f34cc432b4d1f912082 +p410le 849308a1cdf41e055019cf311d1b2201 +p416be 7e7657ab40cf953351a14ea76e296519 +p416le 0991d7fff4e2caf36be219ecdd9619d4 pal8 450b0155d0f2d5628bf95a442db5f817 rgb0 56a7ea69541bcd27bef6a5615784722b rgb24 195e6dae1c3a488b9d3ceb7560d25d85 diff --git a/tests/ref/fate/flv-demux b/tests/ref/fate/flv-demux index 9daee0594e..a7c98d3d76 100644 --- a/tests/ref/fate/flv-demux +++ b/tests/ref/fate/flv-demux @@ -1,6 +1,6 @@ -packet|codec_type=audio|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=46|duration_time=0.046000|size=9|pos=3241|flags=K_side_data|side_data_type=New Extradata +packet|codec_type=audio|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=46|duration_time=0.046000|size=9|pos=3241|flags=K_|side_data|side_data_type=New Extradata |data_hash=CRC32:bbb61b93 -packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=33|duration_time=0.033000|size=135|pos=3267|flags=K_side_data|side_data_type=New Extradata +packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=33|duration_time=0.033000|size=135|pos=3267|flags=K_|side_data|side_data_type=New Extradata |data_hash=CRC32:3f2ccc9e packet|codec_type=video|stream_index=0|pts=33|pts_time=0.033000|dts=33|dts_time=0.033000|duration=33|duration_time=0.033000|size=92|pos=3422|flags=__|data_hash=CRC32:c14e72b2 packet|codec_type=audio|stream_index=1|pts=46|pts_time=0.046000|dts=46|dts_time=0.046000|duration=46|duration_time=0.046000|size=9|pos=3534|flags=K_|data_hash=CRC32:bbb61b93 @@ -603,6 +603,6 @@ packet|codec_type=video|stream_index=0|pts=11612|pts_time=11.612000|dts=11612|dt packet|codec_type=video|stream_index=0|pts=11645|pts_time=11.645000|dts=11645|dts_time=11.645000|duration=33|duration_time=0.033000|size=2600|pos=507811|flags=__|data_hash=CRC32:d35f9e6f packet|codec_type=audio|stream_index=1|pts=11656|pts_time=11.656000|dts=11656|dts_time=11.656000|duration=46|duration_time=0.046000|size=346|pos=510431|flags=K_|data_hash=CRC32:4e6b44cb packet|codec_type=video|stream_index=0|pts=11678|pts_time=11.678000|dts=11678|dts_time=11.678000|duration=33|duration_time=0.033000|size=1190|pos=510794|flags=__|data_hash=CRC32:a0206c90 -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=426|height=240|coded_width=426|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=71:40|pix_fmt=yuv420p|level=21|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=30/1|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=393929|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=351|extradata_hash=CRC32:07b85ca9|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 -stream|index=1|codec_name=aac|profile=1|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=22050|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=67874|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=252|extradata_hash=CRC32:d039c029|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|width=426|height=240|coded_width=426|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=71:40|pix_fmt=yuv420p|level=21|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=true|nal_length_size=4|id=N/A|r_frame_rate=30000/1001|avg_frame_rate=30/1|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=393929|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=351|extradata_size=39|extradata_hash=CRC32:07b85ca9|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=1|codec_name=aac|profile=1|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=22050|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/1000|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=67874|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=252|extradata_size=2|extradata_hash=CRC32:d039c029|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=Enigma_Principles_of_Lust-part.flv|nb_streams=2|nb_programs=0|format_name=flv|start_time=0.000000|duration=210.209999|size=512000|bit_rate=19485|probe_score=100|tag:hasKeyframes=true|tag:hasMetadata=true|tag:datasize=11970544|tag:hasVideo=true|tag:canSeekToEnd=false|tag:lasttimestamp=210|tag:lastkeyframetimestamp=210|tag:audiosize=1791332|tag:hasAudio=true|tag:audiodelay=0|tag:videosize=10176110|tag:metadatadate=2011-02-27T11:00:33.125000Z|tag:metadatacreator=inlet media FLVTool2 v1.0.6 - http://www.inlet-media.de/flvtool2|tag:hasCuePoints=false diff --git a/tests/ref/fate/gapless-mp3-side-data b/tests/ref/fate/gapless-mp3-side-data index f0cfbd4c8c..59907f8ca4 100644 --- a/tests/ref/fate/gapless-mp3-side-data +++ b/tests/ref/fate/gapless-mp3-side-data @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=368640|duration_time=0.026122|size=417|pos=1451|flags=K_side_data|side_data_type=Skip Samples|skip_samples=1105|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=368640|duration_time=0.026122|size=417|pos=1451|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=1105|discard_padding=0|skip_reason=0|discard_reason=0 |data_hash=CRC32:ae0a5066 packet|codec_type=audio|stream_index=0|pts=368640|pts_time=0.026122|dts=368640|dts_time=0.026122|duration=368640|duration_time=0.026122|size=418|pos=1868|flags=K_|data_hash=CRC32:dbb7aa6c packet|codec_type=audio|stream_index=0|pts=737280|pts_time=0.052245|dts=737280|dts_time=0.052245|duration=368640|duration_time=0.026122|size=418|pos=2286|flags=K_|data_hash=CRC32:5fe9fd6b @@ -592,9 +592,9 @@ packet|codec_type=audio|stream_index=0|pts=217128960|pts_time=15.386122|dts=2171 packet|codec_type=audio|stream_index=0|pts=217497600|pts_time=15.412245|dts=217497600|dts_time=15.412245|duration=368640|duration_time=0.026122|size=418|pos=248046|flags=K_|data_hash=CRC32:dc78174d packet|codec_type=audio|stream_index=0|pts=217866240|pts_time=15.438367|dts=217866240|dts_time=15.438367|duration=368640|duration_time=0.026122|size=418|pos=248464|flags=K_|data_hash=CRC32:0b948a05 packet|codec_type=audio|stream_index=0|pts=218234880|pts_time=15.464490|dts=218234880|dts_time=15.464490|duration=368640|duration_time=0.026122|size=418|pos=248882|flags=K_|data_hash=CRC32:fbc83c3c -packet|codec_type=audio|stream_index=0|pts=218603520|pts_time=15.490612|dts=218603520|dts_time=15.490612|duration=368640|duration_time=0.026122|size=418|pos=249300|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=303|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=218603520|pts_time=15.490612|dts=218603520|dts_time=15.490612|duration=368640|duration_time=0.026122|size=418|pos=249300|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=303|skip_reason=0|discard_reason=0 |data_hash=CRC32:d5fb5f9c -packet|codec_type=audio|stream_index=0|pts=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=218972160|pts_time=15.516735|dts=218972160|dts_time=15.516735|duration=368640|duration_time=0.026122|size=418|pos=249718|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=1152|skip_reason=0|discard_reason=0 |data_hash=CRC32:3789f3cf stream|index=0|codec_name=mp3|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=44100|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/14112000|start_pts=353600|start_time=0.025057|duration_ts=219340800|duration=15.542857|bit_rate=128000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=595|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:encoder=LAME3.93 format|filename=gapless.mp3|nb_streams=1|nb_programs=0|format_name=mp3|start_time=0.025057|duration=15.542857|size=250264|bit_rate=128812|probe_score=51|tag:title=test diff --git a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac index 9b97b61aca..f967ac05bc 100644 --- a/tests/ref/fate/gaplessenc-itunes-to-ipod-aac +++ b/tests/ref/fate/gaplessenc-itunes-to-ipod-aac @@ -7,7 +7,7 @@ duration_ts=103326 start_time=0.000000 duration=2.344000 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| +packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_data| packet|pts=0|dts=0|duration=1024|flags=K_ packet|pts=1024|dts=1024|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessenc-pcm-to-mov-aac b/tests/ref/fate/gaplessenc-pcm-to-mov-aac index 43d13f5bc8..82bed6f936 100644 --- a/tests/ref/fate/gaplessenc-pcm-to-mov-aac +++ b/tests/ref/fate/gaplessenc-pcm-to-mov-aac @@ -7,7 +7,7 @@ duration_ts=529200 start_time=0.000000 duration=12.000000 [/FORMAT] -packet|pts=-1024|dts=-1024|duration=1024|flags=KDside_data| +packet|pts=-1024|dts=-1024|duration=1024|flags=KD|side_data| packet|pts=0|dts=0|duration=1024|flags=K_ packet|pts=1024|dts=1024|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessinfo-itunes1 b/tests/ref/fate/gaplessinfo-itunes1 index 4944c78e3b..841bdb31d0 100644 --- a/tests/ref/fate/gaplessinfo-itunes1 +++ b/tests/ref/fate/gaplessinfo-itunes1 @@ -7,7 +7,7 @@ duration_ts=1294336 start_time=0.047889 duration=29.350023 [/FORMAT] -packet|pts=0|dts=0|duration=1024|flags=K_side_data| +packet|pts=0|dts=0|duration=1024|flags=K_|side_data| packet|pts=1024|dts=1024|duration=1024|flags=K_ packet|pts=2048|dts=2048|duration=1024|flags=K_ diff --git a/tests/ref/fate/gaplessinfo-itunes2 b/tests/ref/fate/gaplessinfo-itunes2 index cf6825d13c..3184a5ea59 100644 --- a/tests/ref/fate/gaplessinfo-itunes2 +++ b/tests/ref/fate/gaplessinfo-itunes2 @@ -7,7 +7,7 @@ duration_ts=105472 start_time=0.047891 duration=2.391655 [/FORMAT] -packet|pts=0|dts=0|duration=1024|flags=K_side_data| +packet|pts=0|dts=0|duration=1024|flags=K_|side_data| packet|pts=1024|dts=1024|duration=1024|flags=K_ packet|pts=2048|dts=2048|duration=1024|flags=K_ diff --git a/tests/ref/fate/hevc-dv-rpu b/tests/ref/fate/hevc-dv-rpu new file mode 100644 index 0000000000..1980ab13ea --- /dev/null +++ b/tests/ref/fate/hevc-dv-rpu @@ -0,0 +1,237 @@ +[FRAME] +[SIDE_DATA] +side_data_type=H.26[45] User Data Unregistered SEI message +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] +[/FRAME] +[FRAME] +[SIDE_DATA] +side_data_type=Dolby Vision RPU Data +[/SIDE_DATA] +[SIDE_DATA] +side_data_type=Dolby Vision Metadata +rpu_type=2 +rpu_format=18 +vdr_rpu_profile=1 +vdr_rpu_level=0 +chroma_resampling_explicit_filter_flag=0 +coef_data_type=0 +coef_log2_denom=23 +vdr_rpu_normalized_idc=1 +bl_video_full_range_flag=0 +bl_bit_depth=10 +el_bit_depth=10 +vdr_bit_depth=12 +spatial_resampling_filter_flag=0 +el_spatial_resampling_filter_flag=0 +disable_residual_flag=1 +vdr_rpu_id=0 +mapping_color_space=0 +mapping_chroma_format_idc=0 +nlq_method_idc=-1 +nlq_method_idc_name=none +num_x_partitions=1 +num_y_partitions=1 +[COMPONENT] +pivots=63 132 362 618 874 911 927 935 942 +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-409680 16721463 -20276640 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=-119056 13575212 -12867889 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=1317527 5338528 -948122 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=2119979 2065496 2288524 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=7982780 -11367226 9973944 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=53792084 -114243184 67724328 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=112973872 -244837568 139764480 +[/SECTION] +[SECTION] +mapping_idc=0 +mapping_idc_name=polynomial +poly_order=2 +poly_coef=236828416 -518849056 291306944 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-4200453 +mmr_coef=9094176 31944476 739652 -27103344 -3431599 -11015088 22758042 -2028643 -30021218 -906885 26272992 7291404 16488745 -78087176 -1487777 12496543 762460 -4281948 -5768035 -7843163 103636960 +[/SECTION] +[/COMPONENT] +[COMPONENT] +pivots=0 1023 +[SECTION] +mapping_idc=1 +mapping_idc_name=mmr +mmr_order=3 +mmr_constant=-10387889 +mmr_coef=29604202 3214133 46206184 -8564340 -53383996 1628407 5426045 -21634202 -5251953 -50812292 19221972 76726656 -425892 -35041240 5917361 2863974 25030554 -14404292 -41230120 1229046 53575140 +[/SECTION] +[/COMPONENT] +dm_metadata_id=0 +scene_refresh_flag=1 +ycc_to_rgb_matrix=9574/8192 0/8192 13802/8192 9574/8192 -1540/8192 -5348/8192 9574/8192 17610/8192 0/8192 +ycc_to_rgb_offset=16777216/268435456 134217728/268435456 134217728/268435456 +rgb_to_lms_matrix=7222/16384 8771/16384 390/16384 2654/16384 12430/16384 1300/16384 0/16384 422/16384 15962/16384 +signal_eotf=65535 +signal_eotf_param0=0 +signal_eotf_param1=0 +signal_eotf_param2=0 +signal_bit_depth=12 +signal_color_space=0 +signal_chroma_format=0 +signal_full_range_flag=1 +source_min_pq=0 +source_max_pq=3079 +source_diagonal=42 +[/SIDE_DATA] +[/FRAME] diff --git a/tests/ref/fate/imf b/tests/ref/fate/imf new file mode 100644 index 0000000000..90b461dc5d --- /dev/null +++ b/tests/ref/fate/imf @@ -0,0 +1,54 @@ +FFMPEG sample content +urn:uuid:8713c020-2489-45f5-a9f7-87be539e20b5 +24000 1001 +Marker resource count: 2 +Marker resource 0 + Marker 0 + Label LFOA + Offset 5 +Marker resource 1 + Marker 0 + Label FFOA + Offset 20 + Marker 1 + Label LFOC + Offset 24 +Main image resource count: 2 +Track file resource 0 + urn:uuid:6f768ca4-c89e-4dac-9056-a29425d40ba1 +Track file resource 1 + urn:uuid:f3b263b3-096b-4360-a952-b1a9623cd0ca +Main audio track count: 2 + Main audio virtual track 0 + Main audio resource count: 2 + Track file resource 0 + urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488 + Track file resource 1 + urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535 + Main audio virtual track 1 + Main audio resource count: 2 + Track file resource 0 + urn:uuid:381dadd2-061e-46cc-a63a-e3d58ce7f488 + Track file resource 1 + urn:uuid:2484d613-bb7d-4bcc-8b0f-2e65938f0535 +Allocate asset map +Parse asset map XML document +Compare assets count: 5 to 5 +For asset: 0: + Compare urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0 to urn:uuid:b5d674b8-c6ce-4bce-3bdf-be045dfdb2d0. + Compare IMF_TEST_ASSET_MAP_video.mxf to IMF_TEST_ASSET_MAP_video.mxf. +For asset: 1: + Compare urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a to urn:uuid:ec3467ec-ab2a-4f49-c8cb-89caa3761f4a. + Compare IMF_TEST_ASSET_MAP_video_1.mxf to IMF_TEST_ASSET_MAP_video_1.mxf. +For asset: 2: + Compare urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6 to urn:uuid:5cf5b5a7-8bb3-4f08-eaa6-3533d4b77fa6. + Compare IMF_TEST_ASSET_MAP_audio.mxf to IMF_TEST_ASSET_MAP_audio.mxf. +For asset: 3: + Compare urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686 to urn:uuid:559777d6-ec29-4375-f90d-300b0bf73686. + Compare CPL_IMF_TEST_ASSET_MAP.xml to CPL_IMF_TEST_ASSET_MAP.xml. +For asset: 4: + Compare urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d to urn:uuid:dd04528d-9b80-452a-7a13-805b08278b3d. + Compare PKL_IMF_TEST_ASSET_MAP.xml to PKL_IMF_TEST_ASSET_MAP.xml. +#### The following should fail #### +CPL parsing failed. +#### End failing test #### diff --git a/tests/ref/fate/imgutils b/tests/ref/fate/imgutils index 495bbd46f0..b23d1b4c39 100644 --- a/tests/ref/fate/imgutils +++ b/tests/ref/fate/imgutils @@ -238,3 +238,11 @@ x2rgb10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 x2rgb10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 x2bgr10le planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 x2bgr10be planes: 1, linesizes: 256 0 0 0, plane_sizes: 12288 0 0 0, plane_offsets: 0 0 0, total_size: 12288 +p210be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p210le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p410be planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p410le planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p216be planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p216le planes: 2, linesizes: 128 128 0 0, plane_sizes: 6144 6144 0 0, plane_offsets: 6144 0 0, total_size: 12288 +p416be planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 +p416le planes: 2, linesizes: 128 256 0 0, plane_sizes: 6144 12288 0 0, plane_offsets: 6144 0 0, total_size: 18432 diff --git a/tests/ref/fate/iv8-demux b/tests/ref/fate/iv8-demux index 5b4cf0d4b0..1ca76a49c3 100644 --- a/tests/ref/fate/iv8-demux +++ b/tests/ref/fate/iv8-demux @@ -27,5 +27,5 @@ 0, 72000, 72000, 3600, 20891, 0x3d064fd3 0, 75600, 75600, 3600, 20834, 0xcb774dbc 0, 79200, 79200, 3600, 20870, 0xbc536589 -0, 82800, 82800, 3600, 21421, 0xc99a68e4 +0, 82800, 82800, 3600, 21421, 0xc99a68e4, F=0x3 0, 86400, 86400, 3600, 12869, 0x5684e304 diff --git a/tests/ref/fate/matroska-dovi-write-config7 b/tests/ref/fate/matroska-dovi-write-config7 new file mode 100644 index 0000000000..1c1422c0e4 --- /dev/null +++ b/tests/ref/fate/matroska-dovi-write-config7 @@ -0,0 +1,49 @@ +3fa1f47c5c3d22b5c33156ff14928d6c *tests/data/fate/matroska-dovi-write-config7.matroska +72758 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-mastering-display-metadata b/tests/ref/fate/matroska-mastering-display-metadata index 627a8c103e..8f5d7b6a22 100644 --- a/tests/ref/fate/matroska-mastering-display-metadata +++ b/tests/ref/fate/matroska-mastering-display-metadata @@ -1,5 +1,5 @@ -4f97d718f706e241df9f6c95ac1c721a *tests/data/fate/matroska-mastering-display-metadata.matroska -1669701 tests/data/fate/matroska-mastering-display-metadata.matroska +542ababe5c088ab925ee49373d8b8a85 *tests/data/fate/matroska-mastering-display-metadata.matroska +1669695 tests/data/fate/matroska-mastering-display-metadata.matroska #extradata 0: 4, 0x040901a3 #extradata 3: 200, 0x506463a8 #tb 0: 1/1000 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 0000000000..46effff53e --- /dev/null +++ b/tests/ref/fate/matroska-move-cues-to-front @@ -0,0 +1,72 @@ +ce15d8b7577933a057c413af505500df *tests/data/fate/matroska-move-cues-to-front.matroska +23210310 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 0: 3 +#channel_layout_name 0: stereo +#tb 1: 1/1000 +#media_type 1: audio +#codec_id 1: pcm_s24le +#sample_rate 1: 192000 +#channel_layout 1: 3 +#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-ms-mode b/tests/ref/fate/matroska-ms-mode new file mode 100644 index 0000000000..5fe052c39b --- /dev/null +++ b/tests/ref/fate/matroska-ms-mode @@ -0,0 +1,89 @@ +b3d928e92bc8b323793a237ce82f9437 *tests/data/fate/matroska-ms-mode.matroska +413108 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 1: 4 +#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-qt-mode b/tests/ref/fate/matroska-qt-mode new file mode 100644 index 0000000000..9dc115cc0d --- /dev/null +++ b/tests/ref/fate/matroska-qt-mode @@ -0,0 +1,125 @@ +a741bd63da27d6b8ce3a21009267703d *tests/data/fate/matroska-qt-mode.matroska +1884278 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 1: 4 +#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/mov-aac-2048-priming b/tests/ref/fate/mov-aac-2048-priming index 5c6361558b..071c3627f3 100644 --- a/tests/ref/fate/mov-aac-2048-priming +++ b/tests/ref/fate/mov-aac-2048-priming @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=-2048|pts_time=-0.046440|dts=-2048|dts_time=-0.046440|duration=1024|duration_time=0.023220|size=258|pos=36|flags=KDside_data|side_data_type=Skip Samples|skip_samples=2048|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=-2048|pts_time=-0.046440|dts=-2048|dts_time=-0.046440|duration=1024|duration_time=0.023220|size=258|pos=36|flags=KD|side_data|side_data_type=Skip Samples|skip_samples=2048|discard_padding=0|skip_reason=0|discard_reason=0 packet|codec_type=audio|stream_index=0|pts=-1024|pts_time=-0.023220|dts=-1024|dts_time=-0.023220|duration=1024|duration_time=0.023220|size=258|pos=294|flags=KD packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=146|pos=552|flags=K_ diff --git a/tests/ref/fate/mov-cover-image b/tests/ref/fate/mov-cover-image index 680d84e061..6141646afa 100644 --- a/tests/ref/fate/mov-cover-image +++ b/tests/ref/fate/mov-cover-image @@ -1,4 +1,4 @@ -4e92f776010bd7a727c11bf8c34cde1e *tests/data/fate/mov-cover-image.mp4 +54a8870d5d1e6cc4da28ae422aa70898 *tests/data/fate/mov-cover-image.mp4 1011919 tests/data/fate/mov-cover-image.mp4 #extradata 0: 2, 0x00340022 #tb 0: 1/44100 diff --git a/tests/ref/fate/mov-mp4-disposition-mpegts-remux b/tests/ref/fate/mov-mp4-disposition-mpegts-remux index 78f1668f65..184b952e04 100644 --- a/tests/ref/fate/mov-mp4-disposition-mpegts-remux +++ b/tests/ref/fate/mov-mp4-disposition-mpegts-remux @@ -1,4 +1,4 @@ -3c4432fe59ffd9f2ed6ba4b122cea935 *tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 +adb3b95c07a5f3e0c86641dd62f01dae *tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 5709 tests/data/fate/mov-mp4-disposition-mpegts-remux.mp4 #tb 0: 1/48000 #media_type 0: audio diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie index cb34bd7f5c..798f47ab84 100644 --- a/tests/ref/fate/mov-zombie +++ b/tests/ref/fate/mov-zombie @@ -1,198 +1,197 @@ packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-3004|dts_time=-0.033378|duration=3003|duration_time=0.033367|size=4133|pos=11309|flags=K_ packet|codec_type=video|stream_index=0|pts=5440|pts_time=0.060444|dts=-567|dts_time=-0.006300|duration=3003|duration_time=0.033367|size=1077|pos=15442|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=11309|pkt_size=4133|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=0|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=2437|pts_time=0.027078|dts=2436|dts_time=0.027067|duration=3003|duration_time=0.033367|size=355|pos=16519|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=2|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=11446|pts_time=0.127178|dts=5439|dts_time=0.060433|duration=3003|duration_time=0.033367|size=1110|pos=16874|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=1|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=1|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=8443|pts_time=0.093811|dts=8442|dts_time=0.093800|duration=3003|duration_time=0.033367|size=430|pos=17984|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=4|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=4|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=17452|pts_time=0.193911|dts=11445|dts_time=0.127167|duration=3003|duration_time=0.033367|size=1485|pos=18414|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=3|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=3|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=14449|pts_time=0.160544|dts=14448|dts_time=0.160533|duration=3003|duration_time=0.033367|size=1005|pos=19899|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=6|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=6|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=23458|pts_time=0.260644|dts=17451|dts_time=0.193900|duration=3003|duration_time=0.033367|size=1976|pos=20904|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=5|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=5|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=20455|pts_time=0.227278|dts=20454|dts_time=0.227267|duration=3003|duration_time=0.033367|size=904|pos=22880|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=8|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=8|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=29464|pts_time=0.327378|dts=23457|dts_time=0.260633|duration=3003|duration_time=0.033367|size=1254|pos=23784|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=7|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=7|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=26461|pts_time=0.294011|dts=26460|dts_time=0.294000|duration=3003|duration_time=0.033367|size=700|pos=25038|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=10|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=10|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=35470|pts_time=0.394111|dts=29463|dts_time=0.327367|duration=3003|duration_time=0.033367|size=1311|pos=25738|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=9|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=9|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=32467|pts_time=0.360744|dts=32466|dts_time=0.360733|duration=3003|duration_time=0.033367|size=631|pos=27049|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=12|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=12|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=41476|pts_time=0.460844|dts=35469|dts_time=0.394100|duration=3003|duration_time=0.033367|size=1296|pos=27680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=11|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=11|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=38473|pts_time=0.427478|dts=38472|dts_time=0.427467|duration=3003|duration_time=0.033367|size=466|pos=28976|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=14|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=14|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=47482|pts_time=0.527578|dts=41475|dts_time=0.460833|duration=3003|duration_time=0.033367|size=1638|pos=29442|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=13|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=13|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=44479|pts_time=0.494211|dts=44478|dts_time=0.494200|duration=3003|duration_time=0.033367|size=907|pos=31080|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=16|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=16|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=53488|pts_time=0.594311|dts=47481|dts_time=0.527567|duration=3003|duration_time=0.033367|size=1362|pos=31987|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=15|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=15|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=50485|pts_time=0.560944|dts=50484|dts_time=0.560933|duration=3003|duration_time=0.033367|size=682|pos=33349|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=18|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=18|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=59494|pts_time=0.661044|dts=53487|dts_time=0.594300|duration=3003|duration_time=0.033367|size=2917|pos=34031|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=17|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=17|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=56491|pts_time=0.627678|dts=56490|dts_time=0.627667|duration=3003|duration_time=0.033367|size=1174|pos=36948|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=20|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=20|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=65500|pts_time=0.727778|dts=59493|dts_time=0.661033|duration=3003|duration_time=0.033367|size=1748|pos=38122|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=19|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=19|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=62497|pts_time=0.694411|dts=62496|dts_time=0.694400|duration=3003|duration_time=0.033367|size=926|pos=39870|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=22|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=22|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=68503|pts_time=0.761144|dts=65499|dts_time=0.727767|duration=3003|duration_time=0.033367|size=918|pos=40796|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=21|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=21|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=71506|pts_time=0.794511|dts=68502|dts_time=0.761133|duration=3003|duration_time=0.033367|size=3846|pos=41714|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=23|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=23|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=77512|pts_time=0.861244|dts=71505|dts_time=0.794500|duration=3003|duration_time=0.033367|size=1932|pos=45560|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=24|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=24|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=74509|pts_time=0.827878|dts=74508|dts_time=0.827867|duration=3003|duration_time=0.033367|size=1159|pos=47492|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=26|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=26|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=83518|pts_time=0.927978|dts=77511|dts_time=0.861233|duration=3003|duration_time=0.033367|size=1522|pos=48651|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=25|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=25|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=80515|pts_time=0.894611|dts=80514|dts_time=0.894600|duration=3003|duration_time=0.033367|size=719|pos=50173|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=28|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=28|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=89524|pts_time=0.994711|dts=83517|dts_time=0.927967|duration=3003|duration_time=0.033367|size=1700|pos=50892|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=27|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=27|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=86521|pts_time=0.961344|dts=86520|dts_time=0.961333|duration=3003|duration_time=0.033367|size=1099|pos=52592|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=30|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=30|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=95530|pts_time=1.061444|dts=89523|dts_time=0.994700|duration=3003|duration_time=0.033367|size=2558|pos=53691|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=29|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=29|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=92527|pts_time=1.028078|dts=92526|dts_time=1.028067|duration=3003|duration_time=0.033367|size=1008|pos=56249|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=32|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=32|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=101536|pts_time=1.128178|dts=95529|dts_time=1.061433|duration=3003|duration_time=0.033367|size=1236|pos=57257|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=31|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=31|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=98533|pts_time=1.094811|dts=98532|dts_time=1.094800|duration=3003|duration_time=0.033367|size=607|pos=58493|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=34|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=34|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=107542|pts_time=1.194911|dts=101535|dts_time=1.128167|duration=3003|duration_time=0.033367|size=1883|pos=59100|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=33|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=33|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=104539|pts_time=1.161544|dts=104538|dts_time=1.161533|duration=3003|duration_time=0.033367|size=893|pos=60983|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=36|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=36|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=113548|pts_time=1.261644|dts=107541|dts_time=1.194900|duration=3003|duration_time=0.033367|size=1305|pos=61876|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=35|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=35|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=110545|pts_time=1.228278|dts=110544|dts_time=1.228267|duration=3003|duration_time=0.033367|size=472|pos=63181|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=38|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=38|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=119554|pts_time=1.328378|dts=113547|dts_time=1.261633|duration=3003|duration_time=0.033367|size=1411|pos=63653|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=37|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=37|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=116551|pts_time=1.295011|dts=116550|dts_time=1.295000|duration=3003|duration_time=0.033367|size=616|pos=65064|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=40|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=40|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=125560|pts_time=1.395111|dts=119553|dts_time=1.328367|duration=3003|duration_time=0.033367|size=1291|pos=65680|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=39|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=39|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=122557|pts_time=1.361744|dts=122556|dts_time=1.361733|duration=3003|duration_time=0.033367|size=470|pos=66971|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=42|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=42|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=131566|pts_time=1.461844|dts=125559|dts_time=1.395100|duration=3003|duration_time=0.033367|size=1977|pos=67441|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=41|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=41|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=128563|pts_time=1.428478|dts=128562|dts_time=1.428467|duration=3003|duration_time=0.033367|size=436|pos=69418|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=44|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=44|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=137572|pts_time=1.528578|dts=131565|dts_time=1.461833|duration=3003|duration_time=0.033367|size=2566|pos=69854|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=43|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=43|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=134569|pts_time=1.495211|dts=134568|dts_time=1.495200|duration=3003|duration_time=0.033367|size=886|pos=72420|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=46|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=46|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=140575|pts_time=1.561944|dts=137571|dts_time=1.528567|duration=3003|duration_time=0.033367|size=1330|pos=73306|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=45|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=45|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=143578|pts_time=1.595311|dts=140574|dts_time=1.561933|duration=3003|duration_time=0.033367|size=2227|pos=74636|flags=K_ -frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=47|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=47|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=149584|pts_time=1.662044|dts=143577|dts_time=1.595300|duration=3003|duration_time=0.033367|size=2210|pos=76863|flags=__ -frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=48|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|coded_picture_number=48|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=146581|pts_time=1.628678|dts=146580|dts_time=1.628667|duration=3003|duration_time=0.033367|size=1498|pos=79073|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=50|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=50|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=155590|pts_time=1.728778|dts=149583|dts_time=1.662033|duration=3003|duration_time=0.033367|size=1721|pos=80571|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=49|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=49|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=152587|pts_time=1.695411|dts=152586|dts_time=1.695400|duration=3003|duration_time=0.033367|size=1238|pos=82292|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=52|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=52|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=161596|pts_time=1.795511|dts=155589|dts_time=1.728767|duration=3003|duration_time=0.033367|size=1753|pos=83530|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=51|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=51|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=158593|pts_time=1.762144|dts=158592|dts_time=1.762133|duration=3003|duration_time=0.033367|size=1014|pos=85283|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=54|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=54|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=167602|pts_time=1.862244|dts=161595|dts_time=1.795500|duration=3003|duration_time=0.033367|size=2408|pos=86297|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=53|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=53|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=164599|pts_time=1.828878|dts=164598|dts_time=1.828867|duration=3003|duration_time=0.033367|size=1727|pos=88705|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=56|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=56|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=173608|pts_time=1.928978|dts=167601|dts_time=1.862233|duration=3003|duration_time=0.033367|size=1504|pos=90432|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=55|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=55|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=170605|pts_time=1.895611|dts=170604|dts_time=1.895600|duration=3003|duration_time=0.033367|size=957|pos=91936|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=58|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=58|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=179614|pts_time=1.995711|dts=173607|dts_time=1.928967|duration=3003|duration_time=0.033367|size=1890|pos=92893|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=57|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=57|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=176611|pts_time=1.962344|dts=176610|dts_time=1.962333|duration=3003|duration_time=0.033367|size=1239|pos=94783|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=60|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=60|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=185620|pts_time=2.062444|dts=179613|dts_time=1.995700|duration=3003|duration_time=0.033367|size=1856|pos=96022|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=59|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=59|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=182617|pts_time=2.029078|dts=182616|dts_time=2.029067|duration=3003|duration_time=0.033367|size=1302|pos=97878|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=62|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=62|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=191626|pts_time=2.129178|dts=185619|dts_time=2.062433|duration=3003|duration_time=0.033367|size=1666|pos=99180|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=61|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=61|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=188623|pts_time=2.095811|dts=188622|dts_time=2.095800|duration=3003|duration_time=0.033367|size=974|pos=100846|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|coded_picture_number=64|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|size=580|pos=101820|flags=__ -frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleftside_data|side_data_type=H.26[45] User Data Unregistered SEI message +frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|pkt_duration=3003|pkt_duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|coded_picture_number=63|display_picture_number=0|interlaced_frame=0|top_field_first=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_data|side_data_type=H.26[45] User Data Unregistered SEI message -stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264 -side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 +stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|extradata_size=34|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264|side_data|side_data_type=Display Matrix|displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|rotation=0 diff --git a/tests/ref/fate/movenc b/tests/ref/fate/movenc index 81ea75f372..19e4e291b8 100644 --- a/tests/ref/fate/movenc +++ b/tests/ref/fate/movenc @@ -7,7 +7,7 @@ write_data len 36, time nopts, type header atom ftyp write_data len 2761, time nopts, type header atom - write_data len 908, time 966667, type sync atom moof write_data len 110, time nopts, type trailer atom - -caf0876986b5f033efc0958c338289cc 3815 non-empty-moov-elst +9d260d424e9de4626163fd25ccce5bab 3815 non-empty-moov-elst write_data len 36, time nopts, type header atom ftyp write_data len 2669, time nopts, type header atom - write_data len 908, time 1000000, type sync atom moof diff --git a/tests/ref/fate/mxf-probe-d10 b/tests/ref/fate/mxf-probe-d10 index 6067f3ef30..b2692c6513 100644 --- a/tests/ref/fate/mxf-probe-d10 +++ b/tests/ref/fate/mxf-probe-d10 @@ -37,6 +37,7 @@ bits_per_raw_sample=N/A nb_frames=N/A nb_read_frames=N/A nb_read_packets=N/A +extradata_size=22 DISPOSITION:default=0 DISPOSITION:dub=0 DISPOSITION:original=0 diff --git a/tests/ref/fate/oggopus-demux b/tests/ref/fate/oggopus-demux index 450ca9f7d5..7ea5dfe8a0 100644 --- a/tests/ref/fate/oggopus-demux +++ b/tests/ref/fate/oggopus-demux @@ -1,4 +1,4 @@ -packet|codec_type=audio|stream_index=0|pts=-356|pts_time=-0.007417|dts=-356|dts_time=-0.007417|duration=960|duration_time=0.020000|size=402|pos=841|flags=K_side_data|side_data_type=Skip Samples|skip_samples=356|discard_padding=0|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=-356|pts_time=-0.007417|dts=-356|dts_time=-0.007417|duration=960|duration_time=0.020000|size=402|pos=841|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=356|discard_padding=0|skip_reason=0|discard_reason=0 |data_hash=CRC32:052ff811 packet|codec_type=audio|stream_index=0|pts=604|pts_time=0.012583|dts=604|dts_time=0.012583|duration=960|duration_time=0.020000|size=216|pos=841|flags=K_|data_hash=CRC32:77f232d3 packet|codec_type=audio|stream_index=0|pts=1564|pts_time=0.032583|dts=1564|dts_time=0.032583|duration=960|duration_time=0.020000|size=215|pos=841|flags=K_|data_hash=CRC32:3746e223 @@ -39,7 +39,7 @@ packet|codec_type=audio|stream_index=0|pts=34204|pts_time=0.712583|dts=34204|dts packet|codec_type=audio|stream_index=0|pts=35164|pts_time=0.732583|dts=35164|dts_time=0.732583|duration=960|duration_time=0.020000|size=219|pos=841|flags=K_|data_hash=CRC32:aba60587 packet|codec_type=audio|stream_index=0|pts=36124|pts_time=0.752583|dts=36124|dts_time=0.752583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:b04fe85a packet|codec_type=audio|stream_index=0|pts=37084|pts_time=0.772583|dts=37084|dts_time=0.772583|duration=960|duration_time=0.020000|size=217|pos=841|flags=K_|data_hash=CRC32:06797ece -packet|codec_type=audio|stream_index=0|pts=38044|pts_time=0.792583|dts=38044|dts_time=0.792583|duration=356|duration_time=0.007417|size=359|pos=841|flags=K_side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 +packet|codec_type=audio|stream_index=0|pts=38044|pts_time=0.792583|dts=38044|dts_time=0.792583|duration=356|duration_time=0.007417|size=359|pos=841|flags=K_|side_data|side_data_type=Skip Samples|skip_samples=0|discard_padding=604|skip_reason=0|discard_reason=0 |data_hash=CRC32:01ca3f8f -stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/48000|start_pts=0|start_time=0.000000|duration_ts=38756|duration=0.807417|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=41|extradata_hash=CRC32:58ba5ff3|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:ENCODER=opusenc from opus-tools 0.1.9|tag:ENCODER_OPTIONS=--discard-comments +stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=[0][0][0][0]|codec_tag=0x0000|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/48000|start_pts=0|start_time=0.000000|duration_ts=38756|duration=0.807417|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=41|extradata_size=19|extradata_hash=CRC32:58ba5ff3|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:ENCODER=opusenc from opus-tools 0.1.9|tag:ENCODER_OPTIONS=--discard-comments format|filename=intro-partial.opus|nb_streams=1|nb_programs=0|format_name=ogg|start_time=0.000000|duration=0.807417|size=10250|bit_rate=101558|probe_score=100 diff --git a/tests/ref/fate/segment-mp4-to-ts b/tests/ref/fate/segment-mp4-to-ts index 8b0746fa92..54fcadb846 100644 --- a/tests/ref/fate/segment-mp4-to-ts +++ b/tests/ref/fate/segment-mp4-to-ts @@ -23,7 +23,7 @@ 0, 50400, 54000, 3600, 607, 0xc53c2339, F=0x0, S=1, 1 0, 54000, 72000, 3600, 4755, 0x2f642b58, F=0x0, S=1, 1 0, 57600, 64800, 3600, 1182, 0xbe1a4847, F=0x0, S=1, 1 -0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x0, S=1, 1 +0, 61200, 61200, 3600, 809, 0x8d948a4e, F=0x2, S=1, 1 0, 64800, 68400, 3600, 656, 0x4fa03c2b, F=0x0, S=1, 1 0, 68400, 86400, 3600, 26555, 0x5629b584, S=1, 1 0, 72000, 79200, 3600, 1141, 0x761b31e8, F=0x0, S=1, 1 @@ -47,7 +47,7 @@ 0, 136800, 140400, 3600, 754, 0xab1c815e, F=0x0, S=1, 1 0, 140400, 158400, 3600, 5328, 0xd2c55ac6, F=0x0, S=1, 1 0, 144000, 151200, 3600, 1271, 0x46006870, F=0x0, S=1, 1 -0, 147600, 147600, 3600, 849, 0x94dc99c7, F=0x0, S=1, 1 +0, 147600, 147600, 3600, 849, 0x94dc99c7, F=0x2, S=1, 1 0, 151200, 154800, 3600, 753, 0xf4236cab, F=0x0, S=1, 1 0, 154800, 172800, 3600, 25825, 0xd5464dee, S=1, 1 0, 158400, 165600, 3600, 1206, 0x8ce84344, F=0x0, S=1, 1 @@ -95,7 +95,7 @@ 0, 309600, 313200, 3600, 829, 0xffd795cd, F=0x0, S=1, 1 0, 313200, 331200, 3600, 5352, 0x59997996, F=0x0, S=1, 1 0, 316800, 324000, 3600, 1501, 0xb3b8f001, F=0x0, S=1, 1 -0, 320400, 320400, 3600, 941, 0x92b0cb18, F=0x0, S=1, 1 +0, 320400, 320400, 3600, 941, 0x92b0cb18, F=0x2, S=1, 1 0, 324000, 327600, 3600, 823, 0x3d548355, F=0x0, S=1, 1 0, 327600, 345600, 3600, 24042, 0x441e94fb, S=1, 1 0, 331200, 338400, 3600, 1582, 0x4f5d1049, F=0x0, S=1, 1 @@ -119,7 +119,7 @@ 0, 396000, 399600, 3600, 199, 0x79b06355, F=0x0, S=1, 1 0, 399600, 417600, 3600, 1862, 0x22a2a06c, F=0x0, S=1, 1 0, 403200, 410400, 3600, 359, 0x11bdae52, F=0x0, S=1, 1 -0, 406800, 406800, 3600, 235, 0xbec26964, F=0x0, S=1, 1 +0, 406800, 406800, 3600, 235, 0xbec26964, F=0x2, S=1, 1 0, 410400, 414000, 3600, 221, 0x8380682c, F=0x0, S=1, 1 0, 414000, 432000, 3600, 22588, 0xf0ecf072, S=1, 1 0, 417600, 424800, 3600, 383, 0x4f3bb571, F=0x0, S=1, 1 diff --git a/tests/ref/fate/shortest b/tests/ref/fate/shortest new file mode 100644 index 0000000000..64b5bed312 --- /dev/null +++ b/tests/ref/fate/shortest @@ -0,0 +1,119 @@ +#tb 0: 1/25 +#media_type 0: video +#codec_id 0: mpeg4 +#dimensions 0: 352x288 +#sar 0: 0/1 +#tb 1: 1/44100 +#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 +1, 1280, 1280, 1536, 418, 0xa0ccc09d +0, 1, 1, 1, 975, 0x2fcf0617, F=0x0, S=1, 8 +1, 2816, 2816, 1536, 418, 0xb873cb60 +0, 2, 2, 1, 1167, 0x6d32482b, F=0x0, S=1, 8 +1, 4352, 4352, 1536, 418, 0x1366c008 +0, 3, 3, 1, 1274, 0xab1d80c9, F=0x0, S=1, 8 +1, 5888, 5888, 1536, 418, 0xeb24c8da +0, 4, 4, 1, 1361, 0x9dc28a69, F=0x0, S=1, 8 +1, 7424, 7424, 1536, 418, 0xc75ac55e +0, 5, 5, 1, 1415, 0x41d8ba3e, F=0x0, S=1, 8 +1, 8960, 8960, 1536, 418, 0xe336d28d +1, 10496, 10496, 1536, 418, 0xd0acc452 +0, 6, 6, 1, 1421, 0x8c83ad35, F=0x0, S=1, 8 +1, 12032, 12032, 1536, 418, 0xae88c75f +0, 7, 7, 1, 1474, 0x1025b9b0, F=0x0, S=1, 8 +1, 13568, 13568, 1536, 418, 0xa200b8f0 +0, 8, 8, 1, 1467, 0xf3c0c714, F=0x0, S=1, 8 +1, 15104, 15104, 1536, 418, 0xbbf9cd36 +0, 9, 9, 1, 1469, 0x1b9faf72, F=0x0, S=1, 8 +1, 16640, 16640, 1536, 418, 0x585ec129 +0, 10, 10, 1, 1506, 0x18a9c359, F=0x0, S=1, 8 +1, 18176, 18176, 1536, 418, 0xda1acf75 +0, 11, 11, 1, 1520, 0x0ec1d39a, F=0x0, S=1, 8 +1, 19712, 19712, 1536, 418, 0x9bb2cfeb +0, 12, 12, 1, 8554, 0xfab776e0, S=1, 8 +1, 21248, 21248, 1536, 418, 0x83f2bf72 +1, 22784, 22784, 1536, 418, 0xdb4dcbe8 +0, 13, 13, 1, 1079, 0x13e40cb3, F=0x0, S=1, 8 +1, 24320, 24320, 1536, 418, 0x6813cefa +0, 14, 14, 1, 1343, 0xf0058d2e, F=0x0, S=1, 8 +1, 25856, 25856, 1536, 418, 0x3573d3c5 +0, 15, 15, 1, 1486, 0x1da1c64e, F=0x0, S=1, 8 +1, 27392, 27392, 1536, 418, 0x80c4c8d2 +0, 16, 16, 1, 1491, 0x872dd43d, F=0x0, S=1, 8 +1, 28928, 28928, 1536, 418, 0xaeaac123 +0, 17, 17, 1, 1504, 0x5907c6ca, F=0x0, S=1, 8 +1, 30464, 30464, 1536, 418, 0xe2c9c038 +0, 18, 18, 1, 1481, 0xde66ba0a, F=0x0, S=1, 8 +1, 32000, 32000, 1536, 418, 0x3f37c65b +0, 19, 19, 1, 1521, 0xf46dcef9, F=0x0, S=1, 8 +1, 33536, 33536, 1536, 418, 0xd8e3d1f3 +1, 35072, 35072, 1536, 418, 0x34bdcb46 +0, 20, 20, 1, 1514, 0x001ed7b1, F=0x0, S=1, 8 +1, 36608, 36608, 1536, 418, 0x4e92be94 +0, 21, 21, 1, 1562, 0x3974e095, F=0x0, S=1, 8 +1, 38144, 38144, 1536, 418, 0xa9d8c8d0 +0, 22, 22, 1, 1562, 0xa94bf1fc, F=0x0, S=1, 8 +1, 39680, 39680, 1536, 418, 0xe4c8bc20 +0, 23, 23, 1, 1629, 0xdfcc0234, F=0x0, S=1, 8 +1, 41216, 41216, 1536, 418, 0x2ccac571 +0, 24, 24, 1, 9664, 0xbf319bb0, S=1, 8 +1, 42752, 42752, 1536, 418, 0xd2a0cbff +0, 25, 25, 1, 1239, 0x1f9662f7, F=0x0, S=1, 8 +1, 44288, 44288, 1536, 418, 0xffadb489 +1, 45824, 45824, 1536, 418, 0x1246cae7 +0, 26, 26, 1, 1568, 0xfbf8ed9d, F=0x0, S=1, 8 +1, 47360, 47360, 1536, 418, 0xa74eb1f7 +0, 27, 27, 1, 1641, 0x46aafde5, F=0x0, S=1, 8 +1, 48896, 48896, 1536, 418, 0x98cfc032 +0, 28, 28, 1, 1735, 0xa9363e9b, F=0x0, S=1, 8 +1, 50432, 50432, 1536, 418, 0x42d6c12e +0, 29, 29, 1, 1760, 0x99b82cbc, F=0x0, S=1, 8 +1, 51968, 51968, 1536, 418, 0x2180c196 +0, 30, 30, 1, 1798, 0xc0ba5286, F=0x0, S=1, 8 +1, 53504, 53504, 1536, 418, 0x35f2b4d1 +0, 31, 31, 1, 1830, 0x4e8b4b80, F=0x0, S=1, 8 +1, 55040, 55040, 1536, 418, 0x7b5fc73a +0, 32, 32, 1, 1835, 0x218a69cb, F=0x0, S=1, 8 +1, 56576, 56576, 1536, 418, 0xbccebddd +1, 58112, 58112, 1536, 418, 0x40a1bcc7 +0, 33, 33, 1, 1902, 0x8f2b67d2, F=0x0, S=1, 8 +1, 59648, 59648, 1536, 418, 0xbcafbf6e +0, 34, 34, 1, 1886, 0xf4087481, F=0x0, S=1, 8 +1, 61184, 61184, 1536, 418, 0xb8e4b630 +0, 35, 35, 1, 1949, 0x142c8ac1, F=0x0, S=1, 8 +1, 62720, 62720, 1536, 418, 0xc667bd39 +0, 36, 36, 1, 10806, 0x603680c3, S=1, 8 +1, 64256, 64256, 1536, 418, 0x2985c4ac +0, 37, 37, 1, 1413, 0xc52395a2, F=0x0, S=1, 8 +1, 65792, 65792, 1536, 418, 0xb229b697 +0, 38, 38, 1, 1731, 0xa26a2fb2, F=0x0, S=1, 8 +1, 67328, 67328, 1536, 418, 0xd2eec6d8 +0, 39, 39, 1, 1888, 0xa2995d2a, F=0x0, S=1, 8 +1, 68864, 68864, 1536, 418, 0x74a9c1a9 +1, 70400, 70400, 1536, 418, 0x2d1cc383 +0, 40, 40, 1, 1989, 0x0274904a, F=0x0, S=1, 8 +1, 71936, 71936, 1536, 418, 0x0ad9c88a +0, 41, 41, 1, 1949, 0x66fa8de9, F=0x0, S=1, 8 +1, 73472, 73472, 1536, 418, 0x57accd5f +0, 42, 42, 1, 1956, 0x4e2e831d, F=0x0, S=1, 8 +1, 75008, 75008, 1536, 416, 0x99f5b2b6 +0, 43, 43, 1, 2012, 0x1d75ac7a, F=0x0, S=1, 8 +1, 76544, 76544, 1536, 418, 0xe60fc1af +0, 44, 44, 1, 1995, 0xdc478fec, F=0x0, S=1, 8 +1, 78080, 78080, 1536, 418, 0xebc8c568 +0, 45, 45, 1, 2078, 0x416aaf11, F=0x0, S=1, 8 +1, 79616, 79616, 1536, 418, 0x7361c949 +0, 46, 46, 1, 2116, 0x1416cc81, F=0x0, S=1, 8 +1, 81152, 81152, 1536, 418, 0xebb4bde9 +1, 82688, 82688, 1536, 418, 0x72e8bad1 +0, 47, 47, 1, 2024, 0xf1c1ad7d, F=0x0, S=1, 8 +1, 84224, 84224, 1536, 418, 0xb479b641 +0, 48, 48, 1, 11212, 0xc61a3f0a, S=1, 8 +1, 85760, 85760, 1536, 418, 0xae06ca91 +0, 49, 49, 1, 1423, 0x45fba9e4, F=0x0, S=1, 8 +1, 87296, 87296, 1536, 418, 0x7bdcc3c7 diff --git a/tests/ref/fate/sws-pixdesc-query b/tests/ref/fate/sws-pixdesc-query index a74109c3d7..76104bc5a6 100644 --- a/tests/ref/fate/sws-pixdesc-query +++ b/tests/ref/fate/sws-pixdesc-query @@ -13,6 +13,10 @@ is16BPS: gray16le p016be p016le + p216be + p216le + p416be + p416le rgb48be rgb48le rgba64be @@ -57,6 +61,10 @@ isNBPS: nv20le p010be p010le + p210be + p210le + p410be + p410le x2bgr10be x2bgr10le x2rgb10be @@ -140,6 +148,10 @@ isBE: nv20be p010be p016be + p210be + p216be + p410be + p416be rgb444be rgb48be rgb555be @@ -193,6 +205,14 @@ isYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le uyvy422 uyyvyy411 xyz12be @@ -287,6 +307,14 @@ isPlanarYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le yuv410p yuv411p yuv420p @@ -370,6 +398,14 @@ isSemiPlanarYUV: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le isRGB: 0bgr @@ -751,6 +787,14 @@ Planar: p010le p016be p016le + p210be + p210le + p216be + p216le + p410be + p410le + p416be + p416le yuv410p yuv411p yuv420p @@ -908,3 +952,20 @@ usePal: rgb4_byte rgb8 +DataInHighBits: + p010be + p010le + p210be + p210le + p410be + p410le + xyz12be + xyz12le + y210be + y210le + +SwappedChroma: + nv21 + nv42 + yvyu422 + diff --git a/tests/ref/fate/ts-demux b/tests/ref/fate/ts-demux index 8e7a81da41..a90c65ce1c 100644 --- a/tests/ref/fate/ts-demux +++ b/tests/ref/fate/ts-demux @@ -1,48 +1,47 @@ -packet|codec_type=video|stream_index=0|pts=3912669846|pts_time=43474.109400|dts=3912665342|dts_time=43474.059356|duration=1501|duration_time=0.016678|size=114336|pos=376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912669846|pts_time=43474.109400|dts=3912665342|dts_time=43474.059356|duration=1501|duration_time=0.016678|size=114336|pos=376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:9bc8b561 -packet|codec_type=video|stream_index=0|pts=3912666843|pts_time=43474.076033|dts=3912666843|dts_time=43474.076033|duration=1501|duration_time=0.016678|size=12560|pos=122012|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912666843|pts_time=43474.076033|dts=3912666843|dts_time=43474.076033|duration=1501|duration_time=0.016678|size=12560|pos=122012|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:4f8c97dd -packet|codec_type=video|stream_index=0|pts=3912668345|pts_time=43474.092722|dts=3912668345|dts_time=43474.092722|duration=1501|duration_time=0.016678|size=12704|pos=135548|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912668345|pts_time=43474.092722|dts=3912668345|dts_time=43474.092722|duration=1501|duration_time=0.016678|size=12704|pos=135548|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:27f259db -packet|codec_type=video|stream_index=0|pts=3912674351|pts_time=43474.159456|dts=3912669846|dts_time=43474.109400|duration=1501|duration_time=0.016678|size=51976|pos=149084|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912674351|pts_time=43474.159456|dts=3912669846|dts_time=43474.109400|duration=1501|duration_time=0.016678|size=51976|pos=149084|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a6588b80 -packet|codec_type=video|stream_index=0|pts=3912671348|pts_time=43474.126089|dts=3912671348|dts_time=43474.126089|duration=1501|duration_time=0.016678|size=13096|pos=204356|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912671348|pts_time=43474.126089|dts=3912671348|dts_time=43474.126089|duration=1501|duration_time=0.016678|size=13096|pos=204356|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:33547f9f -packet|codec_type=video|stream_index=0|pts=3912672849|pts_time=43474.142767|dts=3912672849|dts_time=43474.142767|duration=1501|duration_time=0.016678|size=13744|pos=218456|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912672849|pts_time=43474.142767|dts=3912672849|dts_time=43474.142767|duration=1501|duration_time=0.016678|size=13744|pos=218456|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:547f3d4e -packet|codec_type=video|stream_index=0|pts=3912678855|pts_time=43474.209500|dts=3912674351|dts_time=43474.159456|duration=1501|duration_time=0.016678|size=56568|pos=232932|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912678855|pts_time=43474.209500|dts=3912674351|dts_time=43474.159456|duration=1501|duration_time=0.016678|size=56568|pos=232932|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:fb5f4b9e -packet|codec_type=video|stream_index=0|pts=3912675852|pts_time=43474.176133|dts=3912675852|dts_time=43474.176133|duration=1501|duration_time=0.016678|size=14720|pos=293092|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912675852|pts_time=43474.176133|dts=3912675852|dts_time=43474.176133|duration=1501|duration_time=0.016678|size=14720|pos=293092|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:1fb84db4 -packet|codec_type=video|stream_index=0|pts=3912677354|pts_time=43474.192822|dts=3912677354|dts_time=43474.192822|duration=1501|duration_time=0.016678|size=15216|pos=309072|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912677354|pts_time=43474.192822|dts=3912677354|dts_time=43474.192822|duration=1501|duration_time=0.016678|size=15216|pos=309072|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:77516f2c -packet|codec_type=video|stream_index=0|pts=3912683360|pts_time=43474.259556|dts=3912678855|dts_time=43474.209500|duration=1501|duration_time=0.016678|size=61720|pos=325240|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912683360|pts_time=43474.259556|dts=3912678855|dts_time=43474.209500|duration=1501|duration_time=0.016678|size=61720|pos=325240|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:7e6594e5 -packet|codec_type=video|stream_index=0|pts=3912680357|pts_time=43474.226189|dts=3912680357|dts_time=43474.226189|duration=1501|duration_time=0.016678|size=17416|pos=390852|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912680357|pts_time=43474.226189|dts=3912680357|dts_time=43474.226189|duration=1501|duration_time=0.016678|size=17416|pos=390852|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:31c8b89d -packet|codec_type=audio|stream_index=1|pts=3912633305|pts_time=43473.703389|dts=3912633305|dts_time=43473.703389|duration=2880|duration_time=0.032000|size=1536|pos=218080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=1|pts=3912633305|pts_time=43473.703389|dts=3912633305|dts_time=43473.703389|duration=2880|duration_time=0.032000|size=1536|pos=218080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:25b60d38 packet|codec_type=audio|stream_index=1|pts=3912636185|pts_time=43473.735389|dts=3912636185|dts_time=43473.735389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|data_hash=CRC32:d4e30aaf packet|codec_type=audio|stream_index=1|pts=3912639065|pts_time=43473.767389|dts=3912639065|dts_time=43473.767389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|data_hash=CRC32:32d6d14d -packet|codec_type=audio|stream_index=2|pts=3912634060|pts_time=43473.711778|dts=3912634060|dts_time=43473.711778|duration=2880|duration_time=0.032000|size=768|pos=235564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=2|pts=3912634060|pts_time=43473.711778|dts=3912634060|dts_time=43473.711778|duration=2880|duration_time=0.032000|size=768|pos=235564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:34b350c9 packet|codec_type=audio|stream_index=2|pts=3912636940|pts_time=43473.743778|dts=3912636940|dts_time=43473.743778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|data_hash=CRC32:457881f8 packet|codec_type=audio|stream_index=2|pts=3912639820|pts_time=43473.775778|dts=3912639820|dts_time=43473.775778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|data_hash=CRC32:1abb0d9a -packet|codec_type=video|stream_index=0|pts=3912681858|pts_time=43474.242867|dts=3912681858|dts_time=43474.242867|duration=1501|duration_time=0.016678|size=18144|pos=409464|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912681858|pts_time=43474.242867|dts=3912681858|dts_time=43474.242867|duration=1501|duration_time=0.016678|size=18144|pos=409464|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:826f8e8e -packet|codec_type=video|stream_index=0|pts=3912687864|pts_time=43474.309600|dts=3912683360|dts_time=43474.259556|duration=1501|duration_time=0.016678|size=56848|pos=428640|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912687864|pts_time=43474.309600|dts=3912683360|dts_time=43474.259556|duration=1501|duration_time=0.016678|size=56848|pos=428640|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6b15be8c -packet|codec_type=video|stream_index=0|pts=3912684861|pts_time=43474.276233|dts=3912684861|dts_time=43474.276233|duration=1501|duration_time=0.016678|size=16296|pos=489176|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=3912684861|pts_time=43474.276233|dts=3912684861|dts_time=43474.276233|duration=1501|duration_time=0.016678|size=16296|pos=489176|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:911b1649 -packet|codec_type=audio|stream_index=1|pts=3912641945|pts_time=43473.799389|dts=3912641945|dts_time=43473.799389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=1|pts=3912641945|pts_time=43473.799389|dts=3912641945|dts_time=43473.799389|duration=2880|duration_time=0.032000|size=1536|pos=N/A|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d2f2012f -packet|codec_type=audio|stream_index=2|pts=3912642700|pts_time=43473.807778|dts=3912642700|dts_time=43473.807778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=2|pts=3912642700|pts_time=43473.807778|dts=3912642700|dts_time=43473.807778|duration=2880|duration_time=0.032000|size=768|pos=N/A|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3dad674a packet|codec_type=video|stream_index=0|pts=3912686363|pts_time=43474.292922|dts=3912686363|dts_time=43474.292922|duration=1501|duration_time=0.016678|size=4944|pos=506660|flags=__|data_hash=CRC32:54a86cbb packet|codec_type=audio|stream_index=1|pts=3912644825|pts_time=43473.831389|dts=3912644825|dts_time=43473.831389|duration=2880|duration_time=0.032000|size=906|pos=474888|flags=K_|data_hash=CRC32:0893d398 packet|codec_type=audio|stream_index=2|pts=3912645580|pts_time=43473.839778|dts=3912645580|dts_time=43473.839778|duration=2880|duration_time=0.032000|size=354|pos=491808|flags=K_|data_hash=CRC32:f5963fa6 -stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 -side_data|side_data_type=CPB properties|max_bitrate=15000000|min_bitrate=0|avg_bitrate=0|buffer_size=9781248|vbv_delay=-1 +stream|index=0|codec_name=mpeg2video|profile=4|codec_type=video|codec_tag_string=[2][0][0][0]|codec_tag=0x0002|width=1280|height=720|coded_width=0|coded_height=0|closed_captions=0|film_grain=0|has_b_frames=1|sample_aspect_ratio=1:1|display_aspect_ratio=16:9|pix_fmt=yuv420p|level=4|color_range=tv|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|id=0x31|r_frame_rate=60000/1001|avg_frame_rate=60000/1001|time_base=1/90000|start_pts=3912669846|start_time=43474.109400|duration_ts=19519|duration=0.216878|bit_rate=15000000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=15|extradata_size=150|extradata_hash=CRC32:53134fa8|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|side_data|side_data_type=CPB properties|max_bitrate=15000000|min_bitrate=0|avg_bitrate=0|buffer_size=9781248|vbv_delay=-1 stream|index=1|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=6|channel_layout=5.1(side)|bits_per_sample=0|id=0x34|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912633305|start_time=43473.703389|duration_ts=14400|duration=0.160000|bit_rate=384000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=eng stream|index=2|codec_name=ac3|profile=unknown|codec_type=audio|codec_tag_string=[4][0][0][0]|codec_tag=0x0004|sample_fmt=fltp|sample_rate=48000|channels=2|channel_layout=stereo|bits_per_sample=0|id=0x35|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=3912634060|start_time=43473.711778|duration_ts=14400|duration=0.160000|bit_rate=192000|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=5|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|tag:language=es format|filename=mp3ac325-4864-small.ts|nb_streams=3|nb_programs=1|format_name=mpegts|start_time=43473.703389|duration=0.622889|size=512000|bit_rate=6575810|probe_score=50 diff --git a/tests/ref/fate/ts-opus-demux b/tests/ref/fate/ts-opus-demux index 722fa74916..ba6059a019 100644 --- a/tests/ref/fate/ts-opus-demux +++ b/tests/ref/fate/ts-opus-demux @@ -1,1026 +1,1026 @@ -packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1800|duration_time=0.020000|size=744|pos=376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1800|duration_time=0.020000|size=744|pos=376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:eec8d060 -packet|codec_type=audio|stream_index=0|pts=1800|pts_time=0.020000|dts=1800|dts_time=0.020000|duration=1800|duration_time=0.020000|size=743|pos=1316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=1800|pts_time=0.020000|dts=1800|dts_time=0.020000|duration=1800|duration_time=0.020000|size=743|pos=1316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5307335 -packet|codec_type=audio|stream_index=0|pts=3600|pts_time=0.040000|dts=3600|dts_time=0.040000|duration=1800|duration_time=0.020000|size=747|pos=2256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=3600|pts_time=0.040000|dts=3600|dts_time=0.040000|duration=1800|duration_time=0.020000|size=747|pos=2256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f1c0bfa -packet|codec_type=audio|stream_index=0|pts=5400|pts_time=0.060000|dts=5400|dts_time=0.060000|duration=1800|duration_time=0.020000|size=742|pos=3196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=5400|pts_time=0.060000|dts=5400|dts_time=0.060000|duration=1800|duration_time=0.020000|size=742|pos=3196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:765b2eab -packet|codec_type=audio|stream_index=0|pts=7200|pts_time=0.080000|dts=7200|dts_time=0.080000|duration=1800|duration_time=0.020000|size=752|pos=4136|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=7200|pts_time=0.080000|dts=7200|dts_time=0.080000|duration=1800|duration_time=0.020000|size=752|pos=4136|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:490463dd -packet|codec_type=audio|stream_index=0|pts=9000|pts_time=0.100000|dts=9000|dts_time=0.100000|duration=1800|duration_time=0.020000|size=753|pos=5076|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=9000|pts_time=0.100000|dts=9000|dts_time=0.100000|duration=1800|duration_time=0.020000|size=753|pos=5076|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:beef1221 -packet|codec_type=audio|stream_index=0|pts=10800|pts_time=0.120000|dts=10800|dts_time=0.120000|duration=1800|duration_time=0.020000|size=756|pos=6016|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=10800|pts_time=0.120000|dts=10800|dts_time=0.120000|duration=1800|duration_time=0.020000|size=756|pos=6016|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7814e1fe -packet|codec_type=audio|stream_index=0|pts=12600|pts_time=0.140000|dts=12600|dts_time=0.140000|duration=1800|duration_time=0.020000|size=761|pos=6956|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=12600|pts_time=0.140000|dts=12600|dts_time=0.140000|duration=1800|duration_time=0.020000|size=761|pos=6956|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1e28bf7d -packet|codec_type=audio|stream_index=0|pts=14400|pts_time=0.160000|dts=14400|dts_time=0.160000|duration=1800|duration_time=0.020000|size=755|pos=7896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=14400|pts_time=0.160000|dts=14400|dts_time=0.160000|duration=1800|duration_time=0.020000|size=755|pos=7896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ac39390f -packet|codec_type=audio|stream_index=0|pts=16200|pts_time=0.180000|dts=16200|dts_time=0.180000|duration=1800|duration_time=0.020000|size=760|pos=8836|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=16200|pts_time=0.180000|dts=16200|dts_time=0.180000|duration=1800|duration_time=0.020000|size=760|pos=8836|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:56129f6c -packet|codec_type=audio|stream_index=0|pts=18000|pts_time=0.200000|dts=18000|dts_time=0.200000|duration=1800|duration_time=0.020000|size=759|pos=10152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=18000|pts_time=0.200000|dts=18000|dts_time=0.200000|duration=1800|duration_time=0.020000|size=759|pos=10152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:444cf0b3 -packet|codec_type=audio|stream_index=0|pts=19800|pts_time=0.220000|dts=19800|dts_time=0.220000|duration=1800|duration_time=0.020000|size=760|pos=11092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=19800|pts_time=0.220000|dts=19800|dts_time=0.220000|duration=1800|duration_time=0.020000|size=760|pos=11092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b26188cc -packet|codec_type=audio|stream_index=0|pts=21600|pts_time=0.240000|dts=21600|dts_time=0.240000|duration=1800|duration_time=0.020000|size=762|pos=12032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=21600|pts_time=0.240000|dts=21600|dts_time=0.240000|duration=1800|duration_time=0.020000|size=762|pos=12032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:550b5ea5 -packet|codec_type=audio|stream_index=0|pts=23400|pts_time=0.260000|dts=23400|dts_time=0.260000|duration=1800|duration_time=0.020000|size=761|pos=12972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=23400|pts_time=0.260000|dts=23400|dts_time=0.260000|duration=1800|duration_time=0.020000|size=761|pos=12972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3b587071 -packet|codec_type=audio|stream_index=0|pts=25200|pts_time=0.280000|dts=25200|dts_time=0.280000|duration=1800|duration_time=0.020000|size=758|pos=13912|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=25200|pts_time=0.280000|dts=25200|dts_time=0.280000|duration=1800|duration_time=0.020000|size=758|pos=13912|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c655d80f -packet|codec_type=audio|stream_index=0|pts=27000|pts_time=0.300000|dts=27000|dts_time=0.300000|duration=1800|duration_time=0.020000|size=756|pos=14852|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=27000|pts_time=0.300000|dts=27000|dts_time=0.300000|duration=1800|duration_time=0.020000|size=756|pos=14852|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4734bf58 -packet|codec_type=audio|stream_index=0|pts=28800|pts_time=0.320000|dts=28800|dts_time=0.320000|duration=1800|duration_time=0.020000|size=762|pos=15792|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=28800|pts_time=0.320000|dts=28800|dts_time=0.320000|duration=1800|duration_time=0.020000|size=762|pos=15792|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:58ddcd0e -packet|codec_type=audio|stream_index=0|pts=30600|pts_time=0.340000|dts=30600|dts_time=0.340000|duration=1800|duration_time=0.020000|size=763|pos=16732|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=30600|pts_time=0.340000|dts=30600|dts_time=0.340000|duration=1800|duration_time=0.020000|size=763|pos=16732|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:50786001 -packet|codec_type=audio|stream_index=0|pts=32400|pts_time=0.360000|dts=32400|dts_time=0.360000|duration=1800|duration_time=0.020000|size=765|pos=17672|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=32400|pts_time=0.360000|dts=32400|dts_time=0.360000|duration=1800|duration_time=0.020000|size=765|pos=17672|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4c8c5dc8 -packet|codec_type=audio|stream_index=0|pts=34200|pts_time=0.380000|dts=34200|dts_time=0.380000|duration=1800|duration_time=0.020000|size=772|pos=18612|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=34200|pts_time=0.380000|dts=34200|dts_time=0.380000|duration=1800|duration_time=0.020000|size=772|pos=18612|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad3f1eda -packet|codec_type=audio|stream_index=0|pts=36000|pts_time=0.400000|dts=36000|dts_time=0.400000|duration=1800|duration_time=0.020000|size=817|pos=19928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=36000|pts_time=0.400000|dts=36000|dts_time=0.400000|duration=1800|duration_time=0.020000|size=817|pos=19928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8b7c8437 -packet|codec_type=audio|stream_index=0|pts=37800|pts_time=0.420000|dts=37800|dts_time=0.420000|duration=1800|duration_time=0.020000|size=828|pos=20868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=37800|pts_time=0.420000|dts=37800|dts_time=0.420000|duration=1800|duration_time=0.020000|size=828|pos=20868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c52621e3 -packet|codec_type=audio|stream_index=0|pts=39600|pts_time=0.440000|dts=39600|dts_time=0.440000|duration=1800|duration_time=0.020000|size=952|pos=21808|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=39600|pts_time=0.440000|dts=39600|dts_time=0.440000|duration=1800|duration_time=0.020000|size=952|pos=21808|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b34b632 -packet|codec_type=audio|stream_index=0|pts=41400|pts_time=0.460000|dts=41400|dts_time=0.460000|duration=1800|duration_time=0.020000|size=819|pos=22936|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=41400|pts_time=0.460000|dts=41400|dts_time=0.460000|duration=1800|duration_time=0.020000|size=819|pos=22936|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79f06d2c -packet|codec_type=audio|stream_index=0|pts=43200|pts_time=0.480000|dts=43200|dts_time=0.480000|duration=1800|duration_time=0.020000|size=816|pos=23876|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=43200|pts_time=0.480000|dts=43200|dts_time=0.480000|duration=1800|duration_time=0.020000|size=816|pos=23876|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:31136ff8 -packet|codec_type=audio|stream_index=0|pts=45000|pts_time=0.500000|dts=45000|dts_time=0.500000|duration=1800|duration_time=0.020000|size=825|pos=24816|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=45000|pts_time=0.500000|dts=45000|dts_time=0.500000|duration=1800|duration_time=0.020000|size=825|pos=24816|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d6cd17f2 -packet|codec_type=audio|stream_index=0|pts=46800|pts_time=0.520000|dts=46800|dts_time=0.520000|duration=1800|duration_time=0.020000|size=814|pos=25756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=46800|pts_time=0.520000|dts=46800|dts_time=0.520000|duration=1800|duration_time=0.020000|size=814|pos=25756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bd4ada7b -packet|codec_type=audio|stream_index=0|pts=48600|pts_time=0.540000|dts=48600|dts_time=0.540000|duration=1800|duration_time=0.020000|size=824|pos=26696|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=48600|pts_time=0.540000|dts=48600|dts_time=0.540000|duration=1800|duration_time=0.020000|size=824|pos=26696|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59132b5d -packet|codec_type=audio|stream_index=0|pts=50400|pts_time=0.560000|dts=50400|dts_time=0.560000|duration=1800|duration_time=0.020000|size=815|pos=27636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=50400|pts_time=0.560000|dts=50400|dts_time=0.560000|duration=1800|duration_time=0.020000|size=815|pos=27636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6d3ba392 -packet|codec_type=audio|stream_index=0|pts=52200|pts_time=0.580000|dts=52200|dts_time=0.580000|duration=1800|duration_time=0.020000|size=824|pos=28576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=52200|pts_time=0.580000|dts=52200|dts_time=0.580000|duration=1800|duration_time=0.020000|size=824|pos=28576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b9341220 -packet|codec_type=audio|stream_index=0|pts=54000|pts_time=0.600000|dts=54000|dts_time=0.600000|duration=1800|duration_time=0.020000|size=822|pos=29892|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=54000|pts_time=0.600000|dts=54000|dts_time=0.600000|duration=1800|duration_time=0.020000|size=822|pos=29892|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cd0b0be2 -packet|codec_type=audio|stream_index=0|pts=55800|pts_time=0.620000|dts=55800|dts_time=0.620000|duration=1800|duration_time=0.020000|size=819|pos=30832|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=55800|pts_time=0.620000|dts=55800|dts_time=0.620000|duration=1800|duration_time=0.020000|size=819|pos=30832|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0a97918 -packet|codec_type=audio|stream_index=0|pts=57600|pts_time=0.640000|dts=57600|dts_time=0.640000|duration=1800|duration_time=0.020000|size=817|pos=31772|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=57600|pts_time=0.640000|dts=57600|dts_time=0.640000|duration=1800|duration_time=0.020000|size=817|pos=31772|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b4da2c7e -packet|codec_type=audio|stream_index=0|pts=59400|pts_time=0.660000|dts=59400|dts_time=0.660000|duration=1800|duration_time=0.020000|size=826|pos=32712|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=59400|pts_time=0.660000|dts=59400|dts_time=0.660000|duration=1800|duration_time=0.020000|size=826|pos=32712|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aaf0a9b2 -packet|codec_type=audio|stream_index=0|pts=61200|pts_time=0.680000|dts=61200|dts_time=0.680000|duration=1800|duration_time=0.020000|size=822|pos=33652|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=61200|pts_time=0.680000|dts=61200|dts_time=0.680000|duration=1800|duration_time=0.020000|size=822|pos=33652|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a09994ed -packet|codec_type=audio|stream_index=0|pts=63000|pts_time=0.700000|dts=63000|dts_time=0.700000|duration=1800|duration_time=0.020000|size=815|pos=34592|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=63000|pts_time=0.700000|dts=63000|dts_time=0.700000|duration=1800|duration_time=0.020000|size=815|pos=34592|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ded67e51 -packet|codec_type=audio|stream_index=0|pts=64800|pts_time=0.720000|dts=64800|dts_time=0.720000|duration=1800|duration_time=0.020000|size=820|pos=35532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=64800|pts_time=0.720000|dts=64800|dts_time=0.720000|duration=1800|duration_time=0.020000|size=820|pos=35532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:17f0a2c0 -packet|codec_type=audio|stream_index=0|pts=66600|pts_time=0.740000|dts=66600|dts_time=0.740000|duration=1800|duration_time=0.020000|size=828|pos=36472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=66600|pts_time=0.740000|dts=66600|dts_time=0.740000|duration=1800|duration_time=0.020000|size=828|pos=36472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:92d1d4ad -packet|codec_type=audio|stream_index=0|pts=68400|pts_time=0.760000|dts=68400|dts_time=0.760000|duration=1800|duration_time=0.020000|size=828|pos=37412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=68400|pts_time=0.760000|dts=68400|dts_time=0.760000|duration=1800|duration_time=0.020000|size=828|pos=37412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3752c787 -packet|codec_type=audio|stream_index=0|pts=70200|pts_time=0.780000|dts=70200|dts_time=0.780000|duration=1800|duration_time=0.020000|size=942|pos=38352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=70200|pts_time=0.780000|dts=70200|dts_time=0.780000|duration=1800|duration_time=0.020000|size=942|pos=38352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab24f03b -packet|codec_type=audio|stream_index=0|pts=72000|pts_time=0.800000|dts=72000|dts_time=0.800000|duration=1800|duration_time=0.020000|size=809|pos=39856|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=72000|pts_time=0.800000|dts=72000|dts_time=0.800000|duration=1800|duration_time=0.020000|size=809|pos=39856|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:920e19f5 -packet|codec_type=audio|stream_index=0|pts=73800|pts_time=0.820000|dts=73800|dts_time=0.820000|duration=1800|duration_time=0.020000|size=823|pos=40796|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=73800|pts_time=0.820000|dts=73800|dts_time=0.820000|duration=1800|duration_time=0.020000|size=823|pos=40796|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:951b6d50 -packet|codec_type=audio|stream_index=0|pts=75600|pts_time=0.840000|dts=75600|dts_time=0.840000|duration=1800|duration_time=0.020000|size=827|pos=41736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=75600|pts_time=0.840000|dts=75600|dts_time=0.840000|duration=1800|duration_time=0.020000|size=827|pos=41736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cfc9eb30 -packet|codec_type=audio|stream_index=0|pts=77400|pts_time=0.860000|dts=77400|dts_time=0.860000|duration=1800|duration_time=0.020000|size=823|pos=42676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=77400|pts_time=0.860000|dts=77400|dts_time=0.860000|duration=1800|duration_time=0.020000|size=823|pos=42676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd66bb72 -packet|codec_type=audio|stream_index=0|pts=79200|pts_time=0.880000|dts=79200|dts_time=0.880000|duration=1800|duration_time=0.020000|size=825|pos=43616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=79200|pts_time=0.880000|dts=79200|dts_time=0.880000|duration=1800|duration_time=0.020000|size=825|pos=43616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:67b1c809 -packet|codec_type=audio|stream_index=0|pts=81000|pts_time=0.900000|dts=81000|dts_time=0.900000|duration=1800|duration_time=0.020000|size=828|pos=44556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=81000|pts_time=0.900000|dts=81000|dts_time=0.900000|duration=1800|duration_time=0.020000|size=828|pos=44556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:94d441b0 -packet|codec_type=audio|stream_index=0|pts=82800|pts_time=0.920000|dts=82800|dts_time=0.920000|duration=1800|duration_time=0.020000|size=823|pos=45496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=82800|pts_time=0.920000|dts=82800|dts_time=0.920000|duration=1800|duration_time=0.020000|size=823|pos=45496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:178471e0 -packet|codec_type=audio|stream_index=0|pts=84600|pts_time=0.940000|dts=84600|dts_time=0.940000|duration=1800|duration_time=0.020000|size=817|pos=46436|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=84600|pts_time=0.940000|dts=84600|dts_time=0.940000|duration=1800|duration_time=0.020000|size=817|pos=46436|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:90e30fb2 -packet|codec_type=audio|stream_index=0|pts=86400|pts_time=0.960000|dts=86400|dts_time=0.960000|duration=1800|duration_time=0.020000|size=813|pos=47376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=86400|pts_time=0.960000|dts=86400|dts_time=0.960000|duration=1800|duration_time=0.020000|size=813|pos=47376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd4e1d03 -packet|codec_type=audio|stream_index=0|pts=88200|pts_time=0.980000|dts=88200|dts_time=0.980000|duration=1800|duration_time=0.020000|size=809|pos=48316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=88200|pts_time=0.980000|dts=88200|dts_time=0.980000|duration=1800|duration_time=0.020000|size=809|pos=48316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e059caf -packet|codec_type=audio|stream_index=0|pts=90000|pts_time=1.000000|dts=90000|dts_time=1.000000|duration=1800|duration_time=0.020000|size=813|pos=49632|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=90000|pts_time=1.000000|dts=90000|dts_time=1.000000|duration=1800|duration_time=0.020000|size=813|pos=49632|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1981fa52 -packet|codec_type=audio|stream_index=0|pts=91800|pts_time=1.020000|dts=91800|dts_time=1.020000|duration=1800|duration_time=0.020000|size=820|pos=50572|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=91800|pts_time=1.020000|dts=91800|dts_time=1.020000|duration=1800|duration_time=0.020000|size=820|pos=50572|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6af0ac25 -packet|codec_type=audio|stream_index=0|pts=93600|pts_time=1.040000|dts=93600|dts_time=1.040000|duration=1800|duration_time=0.020000|size=818|pos=51512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=93600|pts_time=1.040000|dts=93600|dts_time=1.040000|duration=1800|duration_time=0.020000|size=818|pos=51512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ed14497 -packet|codec_type=audio|stream_index=0|pts=95400|pts_time=1.060000|dts=95400|dts_time=1.060000|duration=1800|duration_time=0.020000|size=825|pos=52452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=95400|pts_time=1.060000|dts=95400|dts_time=1.060000|duration=1800|duration_time=0.020000|size=825|pos=52452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b1712b61 -packet|codec_type=audio|stream_index=0|pts=97200|pts_time=1.080000|dts=97200|dts_time=1.080000|duration=1800|duration_time=0.020000|size=808|pos=53392|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=97200|pts_time=1.080000|dts=97200|dts_time=1.080000|duration=1800|duration_time=0.020000|size=808|pos=53392|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:97469bbe -packet|codec_type=audio|stream_index=0|pts=99000|pts_time=1.100000|dts=99000|dts_time=1.100000|duration=1800|duration_time=0.020000|size=774|pos=54332|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=99000|pts_time=1.100000|dts=99000|dts_time=1.100000|duration=1800|duration_time=0.020000|size=774|pos=54332|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f2f922fc -packet|codec_type=audio|stream_index=0|pts=100800|pts_time=1.120000|dts=100800|dts_time=1.120000|duration=1800|duration_time=0.020000|size=774|pos=55272|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=100800|pts_time=1.120000|dts=100800|dts_time=1.120000|duration=1800|duration_time=0.020000|size=774|pos=55272|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:024f521d -packet|codec_type=audio|stream_index=0|pts=102600|pts_time=1.140000|dts=102600|dts_time=1.140000|duration=1800|duration_time=0.020000|size=777|pos=56212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=102600|pts_time=1.140000|dts=102600|dts_time=1.140000|duration=1800|duration_time=0.020000|size=777|pos=56212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:674d82ba -packet|codec_type=audio|stream_index=0|pts=104400|pts_time=1.160000|dts=104400|dts_time=1.160000|duration=1800|duration_time=0.020000|size=776|pos=57152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=104400|pts_time=1.160000|dts=104400|dts_time=1.160000|duration=1800|duration_time=0.020000|size=776|pos=57152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79409537 -packet|codec_type=audio|stream_index=0|pts=106200|pts_time=1.180000|dts=106200|dts_time=1.180000|duration=1800|duration_time=0.020000|size=779|pos=58092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=106200|pts_time=1.180000|dts=106200|dts_time=1.180000|duration=1800|duration_time=0.020000|size=779|pos=58092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aad393ee -packet|codec_type=audio|stream_index=0|pts=108000|pts_time=1.200000|dts=108000|dts_time=1.200000|duration=1800|duration_time=0.020000|size=779|pos=59408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=108000|pts_time=1.200000|dts=108000|dts_time=1.200000|duration=1800|duration_time=0.020000|size=779|pos=59408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9e2dee75 -packet|codec_type=audio|stream_index=0|pts=109800|pts_time=1.220000|dts=109800|dts_time=1.220000|duration=1800|duration_time=0.020000|size=774|pos=60348|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=109800|pts_time=1.220000|dts=109800|dts_time=1.220000|duration=1800|duration_time=0.020000|size=774|pos=60348|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1d8953b4 -packet|codec_type=audio|stream_index=0|pts=111600|pts_time=1.240000|dts=111600|dts_time=1.240000|duration=1800|duration_time=0.020000|size=772|pos=61288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=111600|pts_time=1.240000|dts=111600|dts_time=1.240000|duration=1800|duration_time=0.020000|size=772|pos=61288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3f191e37 -packet|codec_type=audio|stream_index=0|pts=113400|pts_time=1.260000|dts=113400|dts_time=1.260000|duration=1800|duration_time=0.020000|size=779|pos=62228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=113400|pts_time=1.260000|dts=113400|dts_time=1.260000|duration=1800|duration_time=0.020000|size=779|pos=62228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e05df12 -packet|codec_type=audio|stream_index=0|pts=115200|pts_time=1.280000|dts=115200|dts_time=1.280000|duration=1800|duration_time=0.020000|size=774|pos=63168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=115200|pts_time=1.280000|dts=115200|dts_time=1.280000|duration=1800|duration_time=0.020000|size=774|pos=63168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d3d2e07c -packet|codec_type=audio|stream_index=0|pts=117000|pts_time=1.300000|dts=117000|dts_time=1.300000|duration=1800|duration_time=0.020000|size=772|pos=64108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=117000|pts_time=1.300000|dts=117000|dts_time=1.300000|duration=1800|duration_time=0.020000|size=772|pos=64108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:22e0dee4 -packet|codec_type=audio|stream_index=0|pts=118800|pts_time=1.320000|dts=118800|dts_time=1.320000|duration=1800|duration_time=0.020000|size=771|pos=65048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=118800|pts_time=1.320000|dts=118800|dts_time=1.320000|duration=1800|duration_time=0.020000|size=771|pos=65048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e1fae18 -packet|codec_type=audio|stream_index=0|pts=120600|pts_time=1.340000|dts=120600|dts_time=1.340000|duration=1800|duration_time=0.020000|size=776|pos=65988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=120600|pts_time=1.340000|dts=120600|dts_time=1.340000|duration=1800|duration_time=0.020000|size=776|pos=65988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:213724a0 -packet|codec_type=audio|stream_index=0|pts=122400|pts_time=1.360000|dts=122400|dts_time=1.360000|duration=1800|duration_time=0.020000|size=776|pos=66928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=122400|pts_time=1.360000|dts=122400|dts_time=1.360000|duration=1800|duration_time=0.020000|size=776|pos=66928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6018f97 -packet|codec_type=audio|stream_index=0|pts=124200|pts_time=1.380000|dts=124200|dts_time=1.380000|duration=1800|duration_time=0.020000|size=777|pos=67868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=124200|pts_time=1.380000|dts=124200|dts_time=1.380000|duration=1800|duration_time=0.020000|size=777|pos=67868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d917e577 -packet|codec_type=audio|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=1800|duration_time=0.020000|size=779|pos=69184|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=1800|duration_time=0.020000|size=779|pos=69184|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2860d19c -packet|codec_type=audio|stream_index=0|pts=127800|pts_time=1.420000|dts=127800|dts_time=1.420000|duration=1800|duration_time=0.020000|size=779|pos=70124|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=127800|pts_time=1.420000|dts=127800|dts_time=1.420000|duration=1800|duration_time=0.020000|size=779|pos=70124|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:799e404b -packet|codec_type=audio|stream_index=0|pts=129600|pts_time=1.440000|dts=129600|dts_time=1.440000|duration=1800|duration_time=0.020000|size=774|pos=71064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=129600|pts_time=1.440000|dts=129600|dts_time=1.440000|duration=1800|duration_time=0.020000|size=774|pos=71064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a4c43eaa -packet|codec_type=audio|stream_index=0|pts=131400|pts_time=1.460000|dts=131400|dts_time=1.460000|duration=1800|duration_time=0.020000|size=779|pos=72004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=131400|pts_time=1.460000|dts=131400|dts_time=1.460000|duration=1800|duration_time=0.020000|size=779|pos=72004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4aa2d0c3 -packet|codec_type=audio|stream_index=0|pts=133200|pts_time=1.480000|dts=133200|dts_time=1.480000|duration=1800|duration_time=0.020000|size=782|pos=72944|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=133200|pts_time=1.480000|dts=133200|dts_time=1.480000|duration=1800|duration_time=0.020000|size=782|pos=72944|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b5e19460 -packet|codec_type=audio|stream_index=0|pts=135000|pts_time=1.500000|dts=135000|dts_time=1.500000|duration=1800|duration_time=0.020000|size=776|pos=73884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=135000|pts_time=1.500000|dts=135000|dts_time=1.500000|duration=1800|duration_time=0.020000|size=776|pos=73884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:32445f6b -packet|codec_type=audio|stream_index=0|pts=136800|pts_time=1.520000|dts=136800|dts_time=1.520000|duration=1800|duration_time=0.020000|size=778|pos=74824|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=136800|pts_time=1.520000|dts=136800|dts_time=1.520000|duration=1800|duration_time=0.020000|size=778|pos=74824|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f370fec -packet|codec_type=audio|stream_index=0|pts=138600|pts_time=1.540000|dts=138600|dts_time=1.540000|duration=1800|duration_time=0.020000|size=777|pos=75764|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=138600|pts_time=1.540000|dts=138600|dts_time=1.540000|duration=1800|duration_time=0.020000|size=777|pos=75764|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:43e04e6d -packet|codec_type=audio|stream_index=0|pts=140400|pts_time=1.560000|dts=140400|dts_time=1.560000|duration=1800|duration_time=0.020000|size=785|pos=76704|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=140400|pts_time=1.560000|dts=140400|dts_time=1.560000|duration=1800|duration_time=0.020000|size=785|pos=76704|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ed32f7e -packet|codec_type=audio|stream_index=0|pts=142200|pts_time=1.580000|dts=142200|dts_time=1.580000|duration=1800|duration_time=0.020000|size=782|pos=77644|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=142200|pts_time=1.580000|dts=142200|dts_time=1.580000|duration=1800|duration_time=0.020000|size=782|pos=77644|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ead85ef4 -packet|codec_type=audio|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=1800|duration_time=0.020000|size=782|pos=78960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=1800|duration_time=0.020000|size=782|pos=78960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f283747 -packet|codec_type=audio|stream_index=0|pts=145800|pts_time=1.620000|dts=145800|dts_time=1.620000|duration=1800|duration_time=0.020000|size=780|pos=79900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=145800|pts_time=1.620000|dts=145800|dts_time=1.620000|duration=1800|duration_time=0.020000|size=780|pos=79900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4aa30a5 -packet|codec_type=audio|stream_index=0|pts=147600|pts_time=1.640000|dts=147600|dts_time=1.640000|duration=1800|duration_time=0.020000|size=776|pos=80840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=147600|pts_time=1.640000|dts=147600|dts_time=1.640000|duration=1800|duration_time=0.020000|size=776|pos=80840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad09e32c -packet|codec_type=audio|stream_index=0|pts=149400|pts_time=1.660000|dts=149400|dts_time=1.660000|duration=1800|duration_time=0.020000|size=780|pos=81780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=149400|pts_time=1.660000|dts=149400|dts_time=1.660000|duration=1800|duration_time=0.020000|size=780|pos=81780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57f8004d -packet|codec_type=audio|stream_index=0|pts=151200|pts_time=1.680000|dts=151200|dts_time=1.680000|duration=1800|duration_time=0.020000|size=784|pos=82720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=151200|pts_time=1.680000|dts=151200|dts_time=1.680000|duration=1800|duration_time=0.020000|size=784|pos=82720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d862a139 -packet|codec_type=audio|stream_index=0|pts=153000|pts_time=1.700000|dts=153000|dts_time=1.700000|duration=1800|duration_time=0.020000|size=776|pos=83660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=153000|pts_time=1.700000|dts=153000|dts_time=1.700000|duration=1800|duration_time=0.020000|size=776|pos=83660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:29ebd249 -packet|codec_type=audio|stream_index=0|pts=154800|pts_time=1.720000|dts=154800|dts_time=1.720000|duration=1800|duration_time=0.020000|size=777|pos=84600|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=154800|pts_time=1.720000|dts=154800|dts_time=1.720000|duration=1800|duration_time=0.020000|size=777|pos=84600|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5af83f3e -packet|codec_type=audio|stream_index=0|pts=156600|pts_time=1.740000|dts=156600|dts_time=1.740000|duration=1800|duration_time=0.020000|size=783|pos=85540|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=156600|pts_time=1.740000|dts=156600|dts_time=1.740000|duration=1800|duration_time=0.020000|size=783|pos=85540|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:78784213 -packet|codec_type=audio|stream_index=0|pts=158400|pts_time=1.760000|dts=158400|dts_time=1.760000|duration=1800|duration_time=0.020000|size=780|pos=86480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=158400|pts_time=1.760000|dts=158400|dts_time=1.760000|duration=1800|duration_time=0.020000|size=780|pos=86480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cccb4c08 -packet|codec_type=audio|stream_index=0|pts=160200|pts_time=1.780000|dts=160200|dts_time=1.780000|duration=1800|duration_time=0.020000|size=782|pos=87420|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=160200|pts_time=1.780000|dts=160200|dts_time=1.780000|duration=1800|duration_time=0.020000|size=782|pos=87420|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36520804 -packet|codec_type=audio|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=1800|duration_time=0.020000|size=848|pos=88736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=1800|duration_time=0.020000|size=848|pos=88736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9235baa -packet|codec_type=audio|stream_index=0|pts=163800|pts_time=1.820000|dts=163800|dts_time=1.820000|duration=1800|duration_time=0.020000|size=849|pos=89676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=163800|pts_time=1.820000|dts=163800|dts_time=1.820000|duration=1800|duration_time=0.020000|size=849|pos=89676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57ae2eef -packet|codec_type=audio|stream_index=0|pts=165600|pts_time=1.840000|dts=165600|dts_time=1.840000|duration=1800|duration_time=0.020000|size=783|pos=90616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=165600|pts_time=1.840000|dts=165600|dts_time=1.840000|duration=1800|duration_time=0.020000|size=783|pos=90616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:474f3232 -packet|codec_type=audio|stream_index=0|pts=167400|pts_time=1.860000|dts=167400|dts_time=1.860000|duration=1800|duration_time=0.020000|size=784|pos=91556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=167400|pts_time=1.860000|dts=167400|dts_time=1.860000|duration=1800|duration_time=0.020000|size=784|pos=91556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9a51d488 -packet|codec_type=audio|stream_index=0|pts=169200|pts_time=1.880000|dts=169200|dts_time=1.880000|duration=1800|duration_time=0.020000|size=785|pos=92496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=169200|pts_time=1.880000|dts=169200|dts_time=1.880000|duration=1800|duration_time=0.020000|size=785|pos=92496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:919bc794 -packet|codec_type=audio|stream_index=0|pts=171000|pts_time=1.900000|dts=171000|dts_time=1.900000|duration=1800|duration_time=0.020000|size=783|pos=93436|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=171000|pts_time=1.900000|dts=171000|dts_time=1.900000|duration=1800|duration_time=0.020000|size=783|pos=93436|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed8214ad -packet|codec_type=audio|stream_index=0|pts=172800|pts_time=1.920000|dts=172800|dts_time=1.920000|duration=1800|duration_time=0.020000|size=876|pos=94376|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=172800|pts_time=1.920000|dts=172800|dts_time=1.920000|duration=1800|duration_time=0.020000|size=876|pos=94376|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:72fcce4c -packet|codec_type=audio|stream_index=0|pts=174600|pts_time=1.940000|dts=174600|dts_time=1.940000|duration=1800|duration_time=0.020000|size=776|pos=95316|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=174600|pts_time=1.940000|dts=174600|dts_time=1.940000|duration=1800|duration_time=0.020000|size=776|pos=95316|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2a0143f4 -packet|codec_type=audio|stream_index=0|pts=176400|pts_time=1.960000|dts=176400|dts_time=1.960000|duration=1800|duration_time=0.020000|size=787|pos=96256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=176400|pts_time=1.960000|dts=176400|dts_time=1.960000|duration=1800|duration_time=0.020000|size=787|pos=96256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:94f1aae1 -packet|codec_type=audio|stream_index=0|pts=178200|pts_time=1.980000|dts=178200|dts_time=1.980000|duration=1800|duration_time=0.020000|size=781|pos=97196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=178200|pts_time=1.980000|dts=178200|dts_time=1.980000|duration=1800|duration_time=0.020000|size=781|pos=97196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5565737b -packet|codec_type=audio|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=1800|duration_time=0.020000|size=852|pos=98512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=1800|duration_time=0.020000|size=852|pos=98512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:daea61be -packet|codec_type=audio|stream_index=0|pts=181800|pts_time=2.020000|dts=181800|dts_time=2.020000|duration=1800|duration_time=0.020000|size=849|pos=99452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=181800|pts_time=2.020000|dts=181800|dts_time=2.020000|duration=1800|duration_time=0.020000|size=849|pos=99452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee704432 -packet|codec_type=audio|stream_index=0|pts=183600|pts_time=2.040000|dts=183600|dts_time=2.040000|duration=1800|duration_time=0.020000|size=873|pos=100392|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=183600|pts_time=2.040000|dts=183600|dts_time=2.040000|duration=1800|duration_time=0.020000|size=873|pos=100392|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:472aa214 -packet|codec_type=audio|stream_index=0|pts=185400|pts_time=2.060000|dts=185400|dts_time=2.060000|duration=1800|duration_time=0.020000|size=843|pos=101332|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=185400|pts_time=2.060000|dts=185400|dts_time=2.060000|duration=1800|duration_time=0.020000|size=843|pos=101332|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0b046703 -packet|codec_type=audio|stream_index=0|pts=187200|pts_time=2.080000|dts=187200|dts_time=2.080000|duration=1800|duration_time=0.020000|size=841|pos=102272|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=187200|pts_time=2.080000|dts=187200|dts_time=2.080000|duration=1800|duration_time=0.020000|size=841|pos=102272|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59bf9bd5 -packet|codec_type=audio|stream_index=0|pts=189000|pts_time=2.100000|dts=189000|dts_time=2.100000|duration=1800|duration_time=0.020000|size=777|pos=103212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=189000|pts_time=2.100000|dts=189000|dts_time=2.100000|duration=1800|duration_time=0.020000|size=777|pos=103212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:808ee658 -packet|codec_type=audio|stream_index=0|pts=190800|pts_time=2.120000|dts=190800|dts_time=2.120000|duration=1800|duration_time=0.020000|size=846|pos=104152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=190800|pts_time=2.120000|dts=190800|dts_time=2.120000|duration=1800|duration_time=0.020000|size=846|pos=104152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:db581c04 -packet|codec_type=audio|stream_index=0|pts=192600|pts_time=2.140000|dts=192600|dts_time=2.140000|duration=1800|duration_time=0.020000|size=782|pos=105092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=192600|pts_time=2.140000|dts=192600|dts_time=2.140000|duration=1800|duration_time=0.020000|size=782|pos=105092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:768d8d82 -packet|codec_type=audio|stream_index=0|pts=194400|pts_time=2.160000|dts=194400|dts_time=2.160000|duration=1800|duration_time=0.020000|size=869|pos=106032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=194400|pts_time=2.160000|dts=194400|dts_time=2.160000|duration=1800|duration_time=0.020000|size=869|pos=106032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:263c4a83 -packet|codec_type=audio|stream_index=0|pts=196200|pts_time=2.180000|dts=196200|dts_time=2.180000|duration=1800|duration_time=0.020000|size=778|pos=106972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=196200|pts_time=2.180000|dts=196200|dts_time=2.180000|duration=1800|duration_time=0.020000|size=778|pos=106972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4017dc55 -packet|codec_type=audio|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=1800|duration_time=0.020000|size=777|pos=108288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=1800|duration_time=0.020000|size=777|pos=108288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e6b3c398 -packet|codec_type=audio|stream_index=0|pts=199800|pts_time=2.220000|dts=199800|dts_time=2.220000|duration=1800|duration_time=0.020000|size=870|pos=109228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=199800|pts_time=2.220000|dts=199800|dts_time=2.220000|duration=1800|duration_time=0.020000|size=870|pos=109228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:37eda28b -packet|codec_type=audio|stream_index=0|pts=201600|pts_time=2.240000|dts=201600|dts_time=2.240000|duration=1800|duration_time=0.020000|size=782|pos=110168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=201600|pts_time=2.240000|dts=201600|dts_time=2.240000|duration=1800|duration_time=0.020000|size=782|pos=110168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aa3b5d94 -packet|codec_type=audio|stream_index=0|pts=203400|pts_time=2.260000|dts=203400|dts_time=2.260000|duration=1800|duration_time=0.020000|size=777|pos=111108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=203400|pts_time=2.260000|dts=203400|dts_time=2.260000|duration=1800|duration_time=0.020000|size=777|pos=111108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fc87dbf0 -packet|codec_type=audio|stream_index=0|pts=205200|pts_time=2.280000|dts=205200|dts_time=2.280000|duration=1800|duration_time=0.020000|size=869|pos=112048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=205200|pts_time=2.280000|dts=205200|dts_time=2.280000|duration=1800|duration_time=0.020000|size=869|pos=112048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75795b7e -packet|codec_type=audio|stream_index=0|pts=207000|pts_time=2.300000|dts=207000|dts_time=2.300000|duration=1800|duration_time=0.020000|size=772|pos=112988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=207000|pts_time=2.300000|dts=207000|dts_time=2.300000|duration=1800|duration_time=0.020000|size=772|pos=112988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a8a34bb9 -packet|codec_type=audio|stream_index=0|pts=208800|pts_time=2.320000|dts=208800|dts_time=2.320000|duration=1800|duration_time=0.020000|size=775|pos=113928|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=208800|pts_time=2.320000|dts=208800|dts_time=2.320000|duration=1800|duration_time=0.020000|size=775|pos=113928|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2ebc4e7b -packet|codec_type=audio|stream_index=0|pts=210600|pts_time=2.340000|dts=210600|dts_time=2.340000|duration=1800|duration_time=0.020000|size=771|pos=114868|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=210600|pts_time=2.340000|dts=210600|dts_time=2.340000|duration=1800|duration_time=0.020000|size=771|pos=114868|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:53744d32 -packet|codec_type=audio|stream_index=0|pts=212400|pts_time=2.360000|dts=212400|dts_time=2.360000|duration=1800|duration_time=0.020000|size=778|pos=115808|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=212400|pts_time=2.360000|dts=212400|dts_time=2.360000|duration=1800|duration_time=0.020000|size=778|pos=115808|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d32f77ce -packet|codec_type=audio|stream_index=0|pts=214200|pts_time=2.380000|dts=214200|dts_time=2.380000|duration=1800|duration_time=0.020000|size=867|pos=116748|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=214200|pts_time=2.380000|dts=214200|dts_time=2.380000|duration=1800|duration_time=0.020000|size=867|pos=116748|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f582287c -packet|codec_type=audio|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=1800|duration_time=0.020000|size=778|pos=118064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=1800|duration_time=0.020000|size=778|pos=118064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:144b9c4b -packet|codec_type=audio|stream_index=0|pts=217800|pts_time=2.420000|dts=217800|dts_time=2.420000|duration=1800|duration_time=0.020000|size=774|pos=119004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=217800|pts_time=2.420000|dts=217800|dts_time=2.420000|duration=1800|duration_time=0.020000|size=774|pos=119004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0cca881f -packet|codec_type=audio|stream_index=0|pts=219600|pts_time=2.440000|dts=219600|dts_time=2.440000|duration=1800|duration_time=0.020000|size=775|pos=119944|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=219600|pts_time=2.440000|dts=219600|dts_time=2.440000|duration=1800|duration_time=0.020000|size=775|pos=119944|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cddb1237 -packet|codec_type=audio|stream_index=0|pts=221400|pts_time=2.460000|dts=221400|dts_time=2.460000|duration=1800|duration_time=0.020000|size=774|pos=120884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=221400|pts_time=2.460000|dts=221400|dts_time=2.460000|duration=1800|duration_time=0.020000|size=774|pos=120884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:10310b68 -packet|codec_type=audio|stream_index=0|pts=223200|pts_time=2.480000|dts=223200|dts_time=2.480000|duration=1800|duration_time=0.020000|size=774|pos=121824|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=223200|pts_time=2.480000|dts=223200|dts_time=2.480000|duration=1800|duration_time=0.020000|size=774|pos=121824|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dea871f8 -packet|codec_type=audio|stream_index=0|pts=225000|pts_time=2.500000|dts=225000|dts_time=2.500000|duration=1800|duration_time=0.020000|size=772|pos=122764|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=225000|pts_time=2.500000|dts=225000|dts_time=2.500000|duration=1800|duration_time=0.020000|size=772|pos=122764|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d27e8c99 -packet|codec_type=audio|stream_index=0|pts=226800|pts_time=2.520000|dts=226800|dts_time=2.520000|duration=1800|duration_time=0.020000|size=774|pos=123704|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=226800|pts_time=2.520000|dts=226800|dts_time=2.520000|duration=1800|duration_time=0.020000|size=774|pos=123704|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3143b0e0 -packet|codec_type=audio|stream_index=0|pts=228600|pts_time=2.540000|dts=228600|dts_time=2.540000|duration=1800|duration_time=0.020000|size=775|pos=124644|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=228600|pts_time=2.540000|dts=228600|dts_time=2.540000|duration=1800|duration_time=0.020000|size=775|pos=124644|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ebc2c2e6 -packet|codec_type=audio|stream_index=0|pts=230400|pts_time=2.560000|dts=230400|dts_time=2.560000|duration=1800|duration_time=0.020000|size=773|pos=125584|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=230400|pts_time=2.560000|dts=230400|dts_time=2.560000|duration=1800|duration_time=0.020000|size=773|pos=125584|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dc63972d -packet|codec_type=audio|stream_index=0|pts=232200|pts_time=2.580000|dts=232200|dts_time=2.580000|duration=1800|duration_time=0.020000|size=773|pos=126524|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=232200|pts_time=2.580000|dts=232200|dts_time=2.580000|duration=1800|duration_time=0.020000|size=773|pos=126524|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6b141c19 -packet|codec_type=audio|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=1800|duration_time=0.020000|size=769|pos=127840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=1800|duration_time=0.020000|size=769|pos=127840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:752ada1e -packet|codec_type=audio|stream_index=0|pts=235800|pts_time=2.620000|dts=235800|dts_time=2.620000|duration=1800|duration_time=0.020000|size=774|pos=128780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=235800|pts_time=2.620000|dts=235800|dts_time=2.620000|duration=1800|duration_time=0.020000|size=774|pos=128780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36d20d37 -packet|codec_type=audio|stream_index=0|pts=237600|pts_time=2.640000|dts=237600|dts_time=2.640000|duration=1800|duration_time=0.020000|size=779|pos=129720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=237600|pts_time=2.640000|dts=237600|dts_time=2.640000|duration=1800|duration_time=0.020000|size=779|pos=129720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1455dc2e -packet|codec_type=audio|stream_index=0|pts=239400|pts_time=2.660000|dts=239400|dts_time=2.660000|duration=1800|duration_time=0.020000|size=782|pos=130660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=239400|pts_time=2.660000|dts=239400|dts_time=2.660000|duration=1800|duration_time=0.020000|size=782|pos=130660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6ffd5fe -packet|codec_type=audio|stream_index=0|pts=241200|pts_time=2.680000|dts=241200|dts_time=2.680000|duration=1800|duration_time=0.020000|size=779|pos=131600|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=241200|pts_time=2.680000|dts=241200|dts_time=2.680000|duration=1800|duration_time=0.020000|size=779|pos=131600|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e4c83b97 -packet|codec_type=audio|stream_index=0|pts=243000|pts_time=2.700000|dts=243000|dts_time=2.700000|duration=1800|duration_time=0.020000|size=778|pos=132540|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=243000|pts_time=2.700000|dts=243000|dts_time=2.700000|duration=1800|duration_time=0.020000|size=778|pos=132540|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee3f9b5a -packet|codec_type=audio|stream_index=0|pts=244800|pts_time=2.720000|dts=244800|dts_time=2.720000|duration=1800|duration_time=0.020000|size=771|pos=133480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=244800|pts_time=2.720000|dts=244800|dts_time=2.720000|duration=1800|duration_time=0.020000|size=771|pos=133480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7d0ee8b4 -packet|codec_type=audio|stream_index=0|pts=246600|pts_time=2.740000|dts=246600|dts_time=2.740000|duration=1800|duration_time=0.020000|size=775|pos=134420|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=246600|pts_time=2.740000|dts=246600|dts_time=2.740000|duration=1800|duration_time=0.020000|size=775|pos=134420|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:685b64d8 -packet|codec_type=audio|stream_index=0|pts=248400|pts_time=2.760000|dts=248400|dts_time=2.760000|duration=1800|duration_time=0.020000|size=777|pos=135360|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=248400|pts_time=2.760000|dts=248400|dts_time=2.760000|duration=1800|duration_time=0.020000|size=777|pos=135360|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab680b3f -packet|codec_type=audio|stream_index=0|pts=250200|pts_time=2.780000|dts=250200|dts_time=2.780000|duration=1800|duration_time=0.020000|size=773|pos=136300|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=250200|pts_time=2.780000|dts=250200|dts_time=2.780000|duration=1800|duration_time=0.020000|size=773|pos=136300|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8485bf04 -packet|codec_type=audio|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=1800|duration_time=0.020000|size=777|pos=137616|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=1800|duration_time=0.020000|size=777|pos=137616|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60e3ab3b -packet|codec_type=audio|stream_index=0|pts=253800|pts_time=2.820000|dts=253800|dts_time=2.820000|duration=1800|duration_time=0.020000|size=777|pos=138556|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=253800|pts_time=2.820000|dts=253800|dts_time=2.820000|duration=1800|duration_time=0.020000|size=777|pos=138556|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbacc337 -packet|codec_type=audio|stream_index=0|pts=255600|pts_time=2.840000|dts=255600|dts_time=2.840000|duration=1800|duration_time=0.020000|size=908|pos=139496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=255600|pts_time=2.840000|dts=255600|dts_time=2.840000|duration=1800|duration_time=0.020000|size=908|pos=139496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:852be5a3 -packet|codec_type=audio|stream_index=0|pts=257400|pts_time=2.860000|dts=257400|dts_time=2.860000|duration=1800|duration_time=0.020000|size=777|pos=140624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=257400|pts_time=2.860000|dts=257400|dts_time=2.860000|duration=1800|duration_time=0.020000|size=777|pos=140624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:743f04a8 -packet|codec_type=audio|stream_index=0|pts=259200|pts_time=2.880000|dts=259200|dts_time=2.880000|duration=1800|duration_time=0.020000|size=772|pos=141564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=259200|pts_time=2.880000|dts=259200|dts_time=2.880000|duration=1800|duration_time=0.020000|size=772|pos=141564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ed88196 -packet|codec_type=audio|stream_index=0|pts=261000|pts_time=2.900000|dts=261000|dts_time=2.900000|duration=1800|duration_time=0.020000|size=778|pos=142504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=261000|pts_time=2.900000|dts=261000|dts_time=2.900000|duration=1800|duration_time=0.020000|size=778|pos=142504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bf13126e -packet|codec_type=audio|stream_index=0|pts=262800|pts_time=2.920000|dts=262800|dts_time=2.920000|duration=1800|duration_time=0.020000|size=776|pos=143444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=262800|pts_time=2.920000|dts=262800|dts_time=2.920000|duration=1800|duration_time=0.020000|size=776|pos=143444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dd160d29 -packet|codec_type=audio|stream_index=0|pts=264600|pts_time=2.940000|dts=264600|dts_time=2.940000|duration=1800|duration_time=0.020000|size=775|pos=144384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=264600|pts_time=2.940000|dts=264600|dts_time=2.940000|duration=1800|duration_time=0.020000|size=775|pos=144384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65833aa7 -packet|codec_type=audio|stream_index=0|pts=266400|pts_time=2.960000|dts=266400|dts_time=2.960000|duration=1800|duration_time=0.020000|size=772|pos=145324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=266400|pts_time=2.960000|dts=266400|dts_time=2.960000|duration=1800|duration_time=0.020000|size=772|pos=145324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9343d3d2 -packet|codec_type=audio|stream_index=0|pts=268200|pts_time=2.980000|dts=268200|dts_time=2.980000|duration=1800|duration_time=0.020000|size=778|pos=146264|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=268200|pts_time=2.980000|dts=268200|dts_time=2.980000|duration=1800|duration_time=0.020000|size=778|pos=146264|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7da0cd8d -packet|codec_type=audio|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=1800|duration_time=0.020000|size=808|pos=147580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=1800|duration_time=0.020000|size=808|pos=147580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8a3298b7 -packet|codec_type=audio|stream_index=0|pts=271800|pts_time=3.020000|dts=271800|dts_time=3.020000|duration=1800|duration_time=0.020000|size=836|pos=148520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=271800|pts_time=3.020000|dts=271800|dts_time=3.020000|duration=1800|duration_time=0.020000|size=836|pos=148520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:604d40c4 -packet|codec_type=audio|stream_index=0|pts=273600|pts_time=3.040000|dts=273600|dts_time=3.040000|duration=1800|duration_time=0.020000|size=913|pos=149460|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=273600|pts_time=3.040000|dts=273600|dts_time=3.040000|duration=1800|duration_time=0.020000|size=913|pos=149460|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ecd7b491 -packet|codec_type=audio|stream_index=0|pts=275400|pts_time=3.060000|dts=275400|dts_time=3.060000|duration=1800|duration_time=0.020000|size=837|pos=150588|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=275400|pts_time=3.060000|dts=275400|dts_time=3.060000|duration=1800|duration_time=0.020000|size=837|pos=150588|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f8907616 -packet|codec_type=audio|stream_index=0|pts=277200|pts_time=3.080000|dts=277200|dts_time=3.080000|duration=1800|duration_time=0.020000|size=834|pos=151528|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=277200|pts_time=3.080000|dts=277200|dts_time=3.080000|duration=1800|duration_time=0.020000|size=834|pos=151528|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6701edc -packet|codec_type=audio|stream_index=0|pts=279000|pts_time=3.100000|dts=279000|dts_time=3.100000|duration=1800|duration_time=0.020000|size=836|pos=152468|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=279000|pts_time=3.100000|dts=279000|dts_time=3.100000|duration=1800|duration_time=0.020000|size=836|pos=152468|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed85bdee -packet|codec_type=audio|stream_index=0|pts=280800|pts_time=3.120000|dts=280800|dts_time=3.120000|duration=1800|duration_time=0.020000|size=832|pos=153408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=280800|pts_time=3.120000|dts=280800|dts_time=3.120000|duration=1800|duration_time=0.020000|size=832|pos=153408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9ea8517 -packet|codec_type=audio|stream_index=0|pts=282600|pts_time=3.140000|dts=282600|dts_time=3.140000|duration=1800|duration_time=0.020000|size=826|pos=154348|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=282600|pts_time=3.140000|dts=282600|dts_time=3.140000|duration=1800|duration_time=0.020000|size=826|pos=154348|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e396092f -packet|codec_type=audio|stream_index=0|pts=284400|pts_time=3.160000|dts=284400|dts_time=3.160000|duration=1800|duration_time=0.020000|size=817|pos=155288|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=284400|pts_time=3.160000|dts=284400|dts_time=3.160000|duration=1800|duration_time=0.020000|size=817|pos=155288|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c628f31 -packet|codec_type=audio|stream_index=0|pts=286200|pts_time=3.180000|dts=286200|dts_time=3.180000|duration=1800|duration_time=0.020000|size=825|pos=156228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=286200|pts_time=3.180000|dts=286200|dts_time=3.180000|duration=1800|duration_time=0.020000|size=825|pos=156228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52183b8f -packet|codec_type=audio|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=1800|duration_time=0.020000|size=824|pos=157544|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=1800|duration_time=0.020000|size=824|pos=157544|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bbae2882 -packet|codec_type=audio|stream_index=0|pts=289800|pts_time=3.220000|dts=289800|dts_time=3.220000|duration=1800|duration_time=0.020000|size=828|pos=158484|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=289800|pts_time=3.220000|dts=289800|dts_time=3.220000|duration=1800|duration_time=0.020000|size=828|pos=158484|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bb5a7486 -packet|codec_type=audio|stream_index=0|pts=291600|pts_time=3.240000|dts=291600|dts_time=3.240000|duration=1800|duration_time=0.020000|size=833|pos=159424|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=291600|pts_time=3.240000|dts=291600|dts_time=3.240000|duration=1800|duration_time=0.020000|size=833|pos=159424|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ead8306a -packet|codec_type=audio|stream_index=0|pts=293400|pts_time=3.260000|dts=293400|dts_time=3.260000|duration=1800|duration_time=0.020000|size=832|pos=160364|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=293400|pts_time=3.260000|dts=293400|dts_time=3.260000|duration=1800|duration_time=0.020000|size=832|pos=160364|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:82db1098 -packet|codec_type=audio|stream_index=0|pts=295200|pts_time=3.280000|dts=295200|dts_time=3.280000|duration=1800|duration_time=0.020000|size=896|pos=161304|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=295200|pts_time=3.280000|dts=295200|dts_time=3.280000|duration=1800|duration_time=0.020000|size=896|pos=161304|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:688f5cb6 -packet|codec_type=audio|stream_index=0|pts=297000|pts_time=3.300000|dts=297000|dts_time=3.300000|duration=1800|duration_time=0.020000|size=824|pos=162244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=297000|pts_time=3.300000|dts=297000|dts_time=3.300000|duration=1800|duration_time=0.020000|size=824|pos=162244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fdf34c0b -packet|codec_type=audio|stream_index=0|pts=298800|pts_time=3.320000|dts=298800|dts_time=3.320000|duration=1800|duration_time=0.020000|size=812|pos=163184|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=298800|pts_time=3.320000|dts=298800|dts_time=3.320000|duration=1800|duration_time=0.020000|size=812|pos=163184|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:802e95d1 -packet|codec_type=audio|stream_index=0|pts=300600|pts_time=3.340000|dts=300600|dts_time=3.340000|duration=1800|duration_time=0.020000|size=821|pos=164124|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=300600|pts_time=3.340000|dts=300600|dts_time=3.340000|duration=1800|duration_time=0.020000|size=821|pos=164124|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:141404b8 -packet|codec_type=audio|stream_index=0|pts=302400|pts_time=3.360000|dts=302400|dts_time=3.360000|duration=1800|duration_time=0.020000|size=883|pos=165064|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=302400|pts_time=3.360000|dts=302400|dts_time=3.360000|duration=1800|duration_time=0.020000|size=883|pos=165064|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e39e373 -packet|codec_type=audio|stream_index=0|pts=304200|pts_time=3.380000|dts=304200|dts_time=3.380000|duration=1800|duration_time=0.020000|size=820|pos=166004|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=304200|pts_time=3.380000|dts=304200|dts_time=3.380000|duration=1800|duration_time=0.020000|size=820|pos=166004|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ce8d8234 -packet|codec_type=audio|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=1800|duration_time=0.020000|size=835|pos=167320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=1800|duration_time=0.020000|size=835|pos=167320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0f3c194d -packet|codec_type=audio|stream_index=0|pts=307800|pts_time=3.420000|dts=307800|dts_time=3.420000|duration=1800|duration_time=0.020000|size=833|pos=168260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=307800|pts_time=3.420000|dts=307800|dts_time=3.420000|duration=1800|duration_time=0.020000|size=833|pos=168260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3d5d60c4 -packet|codec_type=audio|stream_index=0|pts=309600|pts_time=3.440000|dts=309600|dts_time=3.440000|duration=1800|duration_time=0.020000|size=830|pos=169200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=309600|pts_time=3.440000|dts=309600|dts_time=3.440000|duration=1800|duration_time=0.020000|size=830|pos=169200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f66b2c9f -packet|codec_type=audio|stream_index=0|pts=311400|pts_time=3.460000|dts=311400|dts_time=3.460000|duration=1800|duration_time=0.020000|size=820|pos=170140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=311400|pts_time=3.460000|dts=311400|dts_time=3.460000|duration=1800|duration_time=0.020000|size=820|pos=170140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:44eb2398 -packet|codec_type=audio|stream_index=0|pts=313200|pts_time=3.480000|dts=313200|dts_time=3.480000|duration=1800|duration_time=0.020000|size=815|pos=171080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=313200|pts_time=3.480000|dts=313200|dts_time=3.480000|duration=1800|duration_time=0.020000|size=815|pos=171080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cec1f69c -packet|codec_type=audio|stream_index=0|pts=315000|pts_time=3.500000|dts=315000|dts_time=3.500000|duration=1800|duration_time=0.020000|size=827|pos=172020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=315000|pts_time=3.500000|dts=315000|dts_time=3.500000|duration=1800|duration_time=0.020000|size=827|pos=172020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57096eb1 -packet|codec_type=audio|stream_index=0|pts=316800|pts_time=3.520000|dts=316800|dts_time=3.520000|duration=1800|duration_time=0.020000|size=819|pos=172960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=316800|pts_time=3.520000|dts=316800|dts_time=3.520000|duration=1800|duration_time=0.020000|size=819|pos=172960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:66999a29 -packet|codec_type=audio|stream_index=0|pts=318600|pts_time=3.540000|dts=318600|dts_time=3.540000|duration=1800|duration_time=0.020000|size=828|pos=173900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=318600|pts_time=3.540000|dts=318600|dts_time=3.540000|duration=1800|duration_time=0.020000|size=828|pos=173900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e598023 -packet|codec_type=audio|stream_index=0|pts=320400|pts_time=3.560000|dts=320400|dts_time=3.560000|duration=1800|duration_time=0.020000|size=830|pos=174840|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=320400|pts_time=3.560000|dts=320400|dts_time=3.560000|duration=1800|duration_time=0.020000|size=830|pos=174840|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e728d2b -packet|codec_type=audio|stream_index=0|pts=322200|pts_time=3.580000|dts=322200|dts_time=3.580000|duration=1800|duration_time=0.020000|size=828|pos=175780|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=322200|pts_time=3.580000|dts=322200|dts_time=3.580000|duration=1800|duration_time=0.020000|size=828|pos=175780|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e7549e3 -packet|codec_type=audio|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=1800|duration_time=0.020000|size=829|pos=177096|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=1800|duration_time=0.020000|size=829|pos=177096|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:62f96c18 -packet|codec_type=audio|stream_index=0|pts=325800|pts_time=3.620000|dts=325800|dts_time=3.620000|duration=1800|duration_time=0.020000|size=820|pos=178036|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=325800|pts_time=3.620000|dts=325800|dts_time=3.620000|duration=1800|duration_time=0.020000|size=820|pos=178036|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:48d04b8a -packet|codec_type=audio|stream_index=0|pts=327600|pts_time=3.640000|dts=327600|dts_time=3.640000|duration=1800|duration_time=0.020000|size=823|pos=178976|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=327600|pts_time=3.640000|dts=327600|dts_time=3.640000|duration=1800|duration_time=0.020000|size=823|pos=178976|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7937563e -packet|codec_type=audio|stream_index=0|pts=329400|pts_time=3.660000|dts=329400|dts_time=3.660000|duration=1800|duration_time=0.020000|size=798|pos=179916|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=329400|pts_time=3.660000|dts=329400|dts_time=3.660000|duration=1800|duration_time=0.020000|size=798|pos=179916|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8e573ad0 -packet|codec_type=audio|stream_index=0|pts=331200|pts_time=3.680000|dts=331200|dts_time=3.680000|duration=1800|duration_time=0.020000|size=772|pos=180856|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=331200|pts_time=3.680000|dts=331200|dts_time=3.680000|duration=1800|duration_time=0.020000|size=772|pos=180856|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ece4d7e7 -packet|codec_type=audio|stream_index=0|pts=333000|pts_time=3.700000|dts=333000|dts_time=3.700000|duration=1800|duration_time=0.020000|size=779|pos=181796|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=333000|pts_time=3.700000|dts=333000|dts_time=3.700000|duration=1800|duration_time=0.020000|size=779|pos=181796|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ca26e7d -packet|codec_type=audio|stream_index=0|pts=334800|pts_time=3.720000|dts=334800|dts_time=3.720000|duration=1800|duration_time=0.020000|size=774|pos=182736|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=334800|pts_time=3.720000|dts=334800|dts_time=3.720000|duration=1800|duration_time=0.020000|size=774|pos=182736|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8c347b2d -packet|codec_type=audio|stream_index=0|pts=336600|pts_time=3.740000|dts=336600|dts_time=3.740000|duration=1800|duration_time=0.020000|size=907|pos=183676|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=336600|pts_time=3.740000|dts=336600|dts_time=3.740000|duration=1800|duration_time=0.020000|size=907|pos=183676|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b50e55b8 -packet|codec_type=audio|stream_index=0|pts=338400|pts_time=3.760000|dts=338400|dts_time=3.760000|duration=1800|duration_time=0.020000|size=772|pos=184804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=338400|pts_time=3.760000|dts=338400|dts_time=3.760000|duration=1800|duration_time=0.020000|size=772|pos=184804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e2ff539f -packet|codec_type=audio|stream_index=0|pts=340200|pts_time=3.780000|dts=340200|dts_time=3.780000|duration=1800|duration_time=0.020000|size=777|pos=185744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=340200|pts_time=3.780000|dts=340200|dts_time=3.780000|duration=1800|duration_time=0.020000|size=777|pos=185744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f86e1c5a -packet|codec_type=audio|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=1800|duration_time=0.020000|size=777|pos=187060|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=1800|duration_time=0.020000|size=777|pos=187060|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ff858811 -packet|codec_type=audio|stream_index=0|pts=343800|pts_time=3.820000|dts=343800|dts_time=3.820000|duration=1800|duration_time=0.020000|size=777|pos=188000|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=343800|pts_time=3.820000|dts=343800|dts_time=3.820000|duration=1800|duration_time=0.020000|size=777|pos=188000|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b0da83e -packet|codec_type=audio|stream_index=0|pts=345600|pts_time=3.840000|dts=345600|dts_time=3.840000|duration=1800|duration_time=0.020000|size=775|pos=188940|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=345600|pts_time=3.840000|dts=345600|dts_time=3.840000|duration=1800|duration_time=0.020000|size=775|pos=188940|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:605a41a9 -packet|codec_type=audio|stream_index=0|pts=347400|pts_time=3.860000|dts=347400|dts_time=3.860000|duration=1800|duration_time=0.020000|size=773|pos=189880|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=347400|pts_time=3.860000|dts=347400|dts_time=3.860000|duration=1800|duration_time=0.020000|size=773|pos=189880|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d32c5756 -packet|codec_type=audio|stream_index=0|pts=349200|pts_time=3.880000|dts=349200|dts_time=3.880000|duration=1800|duration_time=0.020000|size=777|pos=190820|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=349200|pts_time=3.880000|dts=349200|dts_time=3.880000|duration=1800|duration_time=0.020000|size=777|pos=190820|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:92c557ef -packet|codec_type=audio|stream_index=0|pts=351000|pts_time=3.900000|dts=351000|dts_time=3.900000|duration=1800|duration_time=0.020000|size=777|pos=191760|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=351000|pts_time=3.900000|dts=351000|dts_time=3.900000|duration=1800|duration_time=0.020000|size=777|pos=191760|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c16056ca -packet|codec_type=audio|stream_index=0|pts=352800|pts_time=3.920000|dts=352800|dts_time=3.920000|duration=1800|duration_time=0.020000|size=776|pos=192700|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=352800|pts_time=3.920000|dts=352800|dts_time=3.920000|duration=1800|duration_time=0.020000|size=776|pos=192700|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c84a2e99 -packet|codec_type=audio|stream_index=0|pts=354600|pts_time=3.940000|dts=354600|dts_time=3.940000|duration=1800|duration_time=0.020000|size=780|pos=193640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=354600|pts_time=3.940000|dts=354600|dts_time=3.940000|duration=1800|duration_time=0.020000|size=780|pos=193640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d59309d0 -packet|codec_type=audio|stream_index=0|pts=356400|pts_time=3.960000|dts=356400|dts_time=3.960000|duration=1800|duration_time=0.020000|size=776|pos=194580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=356400|pts_time=3.960000|dts=356400|dts_time=3.960000|duration=1800|duration_time=0.020000|size=776|pos=194580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8312e1ba -packet|codec_type=audio|stream_index=0|pts=358200|pts_time=3.980000|dts=358200|dts_time=3.980000|duration=1800|duration_time=0.020000|size=778|pos=195520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=358200|pts_time=3.980000|dts=358200|dts_time=3.980000|duration=1800|duration_time=0.020000|size=778|pos=195520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12d77a3e -packet|codec_type=audio|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=1800|duration_time=0.020000|size=774|pos=196836|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=1800|duration_time=0.020000|size=774|pos=196836|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:86b417d4 -packet|codec_type=audio|stream_index=0|pts=361800|pts_time=4.020000|dts=361800|dts_time=4.020000|duration=1800|duration_time=0.020000|size=778|pos=197776|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=361800|pts_time=4.020000|dts=361800|dts_time=4.020000|duration=1800|duration_time=0.020000|size=778|pos=197776|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a66ed4cf -packet|codec_type=audio|stream_index=0|pts=363600|pts_time=4.040000|dts=363600|dts_time=4.040000|duration=1800|duration_time=0.020000|size=777|pos=198716|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=363600|pts_time=4.040000|dts=363600|dts_time=4.040000|duration=1800|duration_time=0.020000|size=777|pos=198716|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b686a5ca -packet|codec_type=audio|stream_index=0|pts=365400|pts_time=4.060000|dts=365400|dts_time=4.060000|duration=1800|duration_time=0.020000|size=773|pos=199656|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=365400|pts_time=4.060000|dts=365400|dts_time=4.060000|duration=1800|duration_time=0.020000|size=773|pos=199656|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:261ce45b -packet|codec_type=audio|stream_index=0|pts=367200|pts_time=4.080000|dts=367200|dts_time=4.080000|duration=1800|duration_time=0.020000|size=782|pos=200596|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=367200|pts_time=4.080000|dts=367200|dts_time=4.080000|duration=1800|duration_time=0.020000|size=782|pos=200596|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbfbd1bf -packet|codec_type=audio|stream_index=0|pts=369000|pts_time=4.100000|dts=369000|dts_time=4.100000|duration=1800|duration_time=0.020000|size=780|pos=201536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=369000|pts_time=4.100000|dts=369000|dts_time=4.100000|duration=1800|duration_time=0.020000|size=780|pos=201536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:20b5484f -packet|codec_type=audio|stream_index=0|pts=370800|pts_time=4.120000|dts=370800|dts_time=4.120000|duration=1800|duration_time=0.020000|size=777|pos=202476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=370800|pts_time=4.120000|dts=370800|dts_time=4.120000|duration=1800|duration_time=0.020000|size=777|pos=202476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c4d54099 -packet|codec_type=audio|stream_index=0|pts=372600|pts_time=4.140000|dts=372600|dts_time=4.140000|duration=1800|duration_time=0.020000|size=775|pos=203416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=372600|pts_time=4.140000|dts=372600|dts_time=4.140000|duration=1800|duration_time=0.020000|size=775|pos=203416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cb665fdf -packet|codec_type=audio|stream_index=0|pts=374400|pts_time=4.160000|dts=374400|dts_time=4.160000|duration=1800|duration_time=0.020000|size=777|pos=204356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=374400|pts_time=4.160000|dts=374400|dts_time=4.160000|duration=1800|duration_time=0.020000|size=777|pos=204356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0271ab1f -packet|codec_type=audio|stream_index=0|pts=376200|pts_time=4.180000|dts=376200|dts_time=4.180000|duration=1800|duration_time=0.020000|size=776|pos=205296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=376200|pts_time=4.180000|dts=376200|dts_time=4.180000|duration=1800|duration_time=0.020000|size=776|pos=205296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a82f4ab4 -packet|codec_type=audio|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=1800|duration_time=0.020000|size=778|pos=206612|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=1800|duration_time=0.020000|size=778|pos=206612|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1e09e3b -packet|codec_type=audio|stream_index=0|pts=379800|pts_time=4.220000|dts=379800|dts_time=4.220000|duration=1800|duration_time=0.020000|size=775|pos=207552|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=379800|pts_time=4.220000|dts=379800|dts_time=4.220000|duration=1800|duration_time=0.020000|size=775|pos=207552|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7b297a73 -packet|codec_type=audio|stream_index=0|pts=381600|pts_time=4.240000|dts=381600|dts_time=4.240000|duration=1800|duration_time=0.020000|size=775|pos=208492|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=381600|pts_time=4.240000|dts=381600|dts_time=4.240000|duration=1800|duration_time=0.020000|size=775|pos=208492|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2165ebef -packet|codec_type=audio|stream_index=0|pts=383400|pts_time=4.260000|dts=383400|dts_time=4.260000|duration=1800|duration_time=0.020000|size=779|pos=209432|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=383400|pts_time=4.260000|dts=383400|dts_time=4.260000|duration=1800|duration_time=0.020000|size=779|pos=209432|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b802ae36 -packet|codec_type=audio|stream_index=0|pts=385200|pts_time=4.280000|dts=385200|dts_time=4.280000|duration=1800|duration_time=0.020000|size=779|pos=210372|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=385200|pts_time=4.280000|dts=385200|dts_time=4.280000|duration=1800|duration_time=0.020000|size=779|pos=210372|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:36ca4657 -packet|codec_type=audio|stream_index=0|pts=387000|pts_time=4.300000|dts=387000|dts_time=4.300000|duration=1800|duration_time=0.020000|size=778|pos=211312|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=387000|pts_time=4.300000|dts=387000|dts_time=4.300000|duration=1800|duration_time=0.020000|size=778|pos=211312|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2fe8a70c -packet|codec_type=audio|stream_index=0|pts=388800|pts_time=4.320000|dts=388800|dts_time=4.320000|duration=1800|duration_time=0.020000|size=780|pos=212252|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=388800|pts_time=4.320000|dts=388800|dts_time=4.320000|duration=1800|duration_time=0.020000|size=780|pos=212252|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:19c3bc8c -packet|codec_type=audio|stream_index=0|pts=390600|pts_time=4.340000|dts=390600|dts_time=4.340000|duration=1800|duration_time=0.020000|size=778|pos=213192|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=390600|pts_time=4.340000|dts=390600|dts_time=4.340000|duration=1800|duration_time=0.020000|size=778|pos=213192|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3b6c08d8 -packet|codec_type=audio|stream_index=0|pts=392400|pts_time=4.360000|dts=392400|dts_time=4.360000|duration=1800|duration_time=0.020000|size=776|pos=214132|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=392400|pts_time=4.360000|dts=392400|dts_time=4.360000|duration=1800|duration_time=0.020000|size=776|pos=214132|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:851471f3 -packet|codec_type=audio|stream_index=0|pts=394200|pts_time=4.380000|dts=394200|dts_time=4.380000|duration=1800|duration_time=0.020000|size=777|pos=215072|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=394200|pts_time=4.380000|dts=394200|dts_time=4.380000|duration=1800|duration_time=0.020000|size=777|pos=215072|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5d33a166 -packet|codec_type=audio|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=1800|duration_time=0.020000|size=841|pos=216388|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=1800|duration_time=0.020000|size=841|pos=216388|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d0d1a21b -packet|codec_type=audio|stream_index=0|pts=397800|pts_time=4.420000|dts=397800|dts_time=4.420000|duration=1800|duration_time=0.020000|size=777|pos=217328|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=397800|pts_time=4.420000|dts=397800|dts_time=4.420000|duration=1800|duration_time=0.020000|size=777|pos=217328|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c21a3376 -packet|codec_type=audio|stream_index=0|pts=399600|pts_time=4.440000|dts=399600|dts_time=4.440000|duration=1800|duration_time=0.020000|size=780|pos=218268|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=399600|pts_time=4.440000|dts=399600|dts_time=4.440000|duration=1800|duration_time=0.020000|size=780|pos=218268|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0daaead6 -packet|codec_type=audio|stream_index=0|pts=401400|pts_time=4.460000|dts=401400|dts_time=4.460000|duration=1800|duration_time=0.020000|size=777|pos=219208|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=401400|pts_time=4.460000|dts=401400|dts_time=4.460000|duration=1800|duration_time=0.020000|size=777|pos=219208|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:01c07956 -packet|codec_type=audio|stream_index=0|pts=403200|pts_time=4.480000|dts=403200|dts_time=4.480000|duration=1800|duration_time=0.020000|size=777|pos=220148|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=403200|pts_time=4.480000|dts=403200|dts_time=4.480000|duration=1800|duration_time=0.020000|size=777|pos=220148|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f5b429c1 -packet|codec_type=audio|stream_index=0|pts=405000|pts_time=4.500000|dts=405000|dts_time=4.500000|duration=1800|duration_time=0.020000|size=778|pos=221088|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=405000|pts_time=4.500000|dts=405000|dts_time=4.500000|duration=1800|duration_time=0.020000|size=778|pos=221088|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a46831d9 -packet|codec_type=audio|stream_index=0|pts=406800|pts_time=4.520000|dts=406800|dts_time=4.520000|duration=1800|duration_time=0.020000|size=778|pos=222028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=406800|pts_time=4.520000|dts=406800|dts_time=4.520000|duration=1800|duration_time=0.020000|size=778|pos=222028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:555d2cb1 -packet|codec_type=audio|stream_index=0|pts=408600|pts_time=4.540000|dts=408600|dts_time=4.540000|duration=1800|duration_time=0.020000|size=779|pos=222968|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=408600|pts_time=4.540000|dts=408600|dts_time=4.540000|duration=1800|duration_time=0.020000|size=779|pos=222968|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7670785c -packet|codec_type=audio|stream_index=0|pts=410400|pts_time=4.560000|dts=410400|dts_time=4.560000|duration=1800|duration_time=0.020000|size=776|pos=223908|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=410400|pts_time=4.560000|dts=410400|dts_time=4.560000|duration=1800|duration_time=0.020000|size=776|pos=223908|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52a244cd -packet|codec_type=audio|stream_index=0|pts=412200|pts_time=4.580000|dts=412200|dts_time=4.580000|duration=1800|duration_time=0.020000|size=784|pos=224848|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=412200|pts_time=4.580000|dts=412200|dts_time=4.580000|duration=1800|duration_time=0.020000|size=784|pos=224848|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7ad67c41 -packet|codec_type=audio|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=1800|duration_time=0.020000|size=776|pos=226164|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=1800|duration_time=0.020000|size=776|pos=226164|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ddc7990b -packet|codec_type=audio|stream_index=0|pts=415800|pts_time=4.620000|dts=415800|dts_time=4.620000|duration=1800|duration_time=0.020000|size=778|pos=227104|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=415800|pts_time=4.620000|dts=415800|dts_time=4.620000|duration=1800|duration_time=0.020000|size=778|pos=227104|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8a49bff6 -packet|codec_type=audio|stream_index=0|pts=417600|pts_time=4.640000|dts=417600|dts_time=4.640000|duration=1800|duration_time=0.020000|size=775|pos=228044|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=417600|pts_time=4.640000|dts=417600|dts_time=4.640000|duration=1800|duration_time=0.020000|size=775|pos=228044|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:258dc60a -packet|codec_type=audio|stream_index=0|pts=419400|pts_time=4.660000|dts=419400|dts_time=4.660000|duration=1800|duration_time=0.020000|size=781|pos=228984|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=419400|pts_time=4.660000|dts=419400|dts_time=4.660000|duration=1800|duration_time=0.020000|size=781|pos=228984|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2dd6d159 -packet|codec_type=audio|stream_index=0|pts=421200|pts_time=4.680000|dts=421200|dts_time=4.680000|duration=1800|duration_time=0.020000|size=779|pos=229924|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=421200|pts_time=4.680000|dts=421200|dts_time=4.680000|duration=1800|duration_time=0.020000|size=779|pos=229924|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:359ba790 -packet|codec_type=audio|stream_index=0|pts=423000|pts_time=4.700000|dts=423000|dts_time=4.700000|duration=1800|duration_time=0.020000|size=846|pos=230864|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=423000|pts_time=4.700000|dts=423000|dts_time=4.700000|duration=1800|duration_time=0.020000|size=846|pos=230864|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:68cbef69 -packet|codec_type=audio|stream_index=0|pts=424800|pts_time=4.720000|dts=424800|dts_time=4.720000|duration=1800|duration_time=0.020000|size=776|pos=231804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=424800|pts_time=4.720000|dts=424800|dts_time=4.720000|duration=1800|duration_time=0.020000|size=776|pos=231804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cbce1c41 -packet|codec_type=audio|stream_index=0|pts=426600|pts_time=4.740000|dts=426600|dts_time=4.740000|duration=1800|duration_time=0.020000|size=781|pos=232744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=426600|pts_time=4.740000|dts=426600|dts_time=4.740000|duration=1800|duration_time=0.020000|size=781|pos=232744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9a19b23 -packet|codec_type=audio|stream_index=0|pts=428400|pts_time=4.760000|dts=428400|dts_time=4.760000|duration=1800|duration_time=0.020000|size=783|pos=233684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=428400|pts_time=4.760000|dts=428400|dts_time=4.760000|duration=1800|duration_time=0.020000|size=783|pos=233684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f31b8def -packet|codec_type=audio|stream_index=0|pts=430200|pts_time=4.780000|dts=430200|dts_time=4.780000|duration=1800|duration_time=0.020000|size=971|pos=234624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=430200|pts_time=4.780000|dts=430200|dts_time=4.780000|duration=1800|duration_time=0.020000|size=971|pos=234624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4dd92879 -packet|codec_type=audio|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=1800|duration_time=0.020000|size=970|pos=236128|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=1800|duration_time=0.020000|size=970|pos=236128|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7020e4a7 -packet|codec_type=audio|stream_index=0|pts=433800|pts_time=4.820000|dts=433800|dts_time=4.820000|duration=1800|duration_time=0.020000|size=967|pos=237256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=433800|pts_time=4.820000|dts=433800|dts_time=4.820000|duration=1800|duration_time=0.020000|size=967|pos=237256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f56efad -packet|codec_type=audio|stream_index=0|pts=435600|pts_time=4.840000|dts=435600|dts_time=4.840000|duration=1800|duration_time=0.020000|size=776|pos=238384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=435600|pts_time=4.840000|dts=435600|dts_time=4.840000|duration=1800|duration_time=0.020000|size=776|pos=238384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4ae7101d -packet|codec_type=audio|stream_index=0|pts=437400|pts_time=4.860000|dts=437400|dts_time=4.860000|duration=1800|duration_time=0.020000|size=971|pos=239324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=437400|pts_time=4.860000|dts=437400|dts_time=4.860000|duration=1800|duration_time=0.020000|size=971|pos=239324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:386c5965 -packet|codec_type=audio|stream_index=0|pts=439200|pts_time=4.880000|dts=439200|dts_time=4.880000|duration=1800|duration_time=0.020000|size=962|pos=240452|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=439200|pts_time=4.880000|dts=439200|dts_time=4.880000|duration=1800|duration_time=0.020000|size=962|pos=240452|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f2701022 -packet|codec_type=audio|stream_index=0|pts=441000|pts_time=4.900000|dts=441000|dts_time=4.900000|duration=1800|duration_time=0.020000|size=964|pos=241580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=441000|pts_time=4.900000|dts=441000|dts_time=4.900000|duration=1800|duration_time=0.020000|size=964|pos=241580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:386bfd07 -packet|codec_type=audio|stream_index=0|pts=442800|pts_time=4.920000|dts=442800|dts_time=4.920000|duration=1800|duration_time=0.020000|size=773|pos=242708|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=442800|pts_time=4.920000|dts=442800|dts_time=4.920000|duration=1800|duration_time=0.020000|size=773|pos=242708|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:080e4345 -packet|codec_type=audio|stream_index=0|pts=444600|pts_time=4.940000|dts=444600|dts_time=4.940000|duration=1800|duration_time=0.020000|size=770|pos=243648|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=444600|pts_time=4.940000|dts=444600|dts_time=4.940000|duration=1800|duration_time=0.020000|size=770|pos=243648|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4fbaa6b9 -packet|codec_type=audio|stream_index=0|pts=446400|pts_time=4.960000|dts=446400|dts_time=4.960000|duration=1800|duration_time=0.020000|size=964|pos=244588|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=446400|pts_time=4.960000|dts=446400|dts_time=4.960000|duration=1800|duration_time=0.020000|size=964|pos=244588|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5c879539 -packet|codec_type=audio|stream_index=0|pts=448200|pts_time=4.980000|dts=448200|dts_time=4.980000|duration=1800|duration_time=0.020000|size=958|pos=245716|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=448200|pts_time=4.980000|dts=448200|dts_time=4.980000|duration=1800|duration_time=0.020000|size=958|pos=245716|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dac40562 -packet|codec_type=audio|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=1800|duration_time=0.020000|size=775|pos=247220|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=1800|duration_time=0.020000|size=775|pos=247220|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:31f989e0 -packet|codec_type=audio|stream_index=0|pts=451800|pts_time=5.020000|dts=451800|dts_time=5.020000|duration=1800|duration_time=0.020000|size=775|pos=248160|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=451800|pts_time=5.020000|dts=451800|dts_time=5.020000|duration=1800|duration_time=0.020000|size=775|pos=248160|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0149cc11 -packet|codec_type=audio|stream_index=0|pts=453600|pts_time=5.040000|dts=453600|dts_time=5.040000|duration=1800|duration_time=0.020000|size=966|pos=249100|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=453600|pts_time=5.040000|dts=453600|dts_time=5.040000|duration=1800|duration_time=0.020000|size=966|pos=249100|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c226514 -packet|codec_type=audio|stream_index=0|pts=455400|pts_time=5.060000|dts=455400|dts_time=5.060000|duration=1800|duration_time=0.020000|size=843|pos=250228|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=455400|pts_time=5.060000|dts=455400|dts_time=5.060000|duration=1800|duration_time=0.020000|size=843|pos=250228|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:991ab49b -packet|codec_type=audio|stream_index=0|pts=457200|pts_time=5.080000|dts=457200|dts_time=5.080000|duration=1800|duration_time=0.020000|size=846|pos=251168|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=457200|pts_time=5.080000|dts=457200|dts_time=5.080000|duration=1800|duration_time=0.020000|size=846|pos=251168|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2803c379 -packet|codec_type=audio|stream_index=0|pts=459000|pts_time=5.100000|dts=459000|dts_time=5.100000|duration=1800|duration_time=0.020000|size=775|pos=252108|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=459000|pts_time=5.100000|dts=459000|dts_time=5.100000|duration=1800|duration_time=0.020000|size=775|pos=252108|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2d95b53b -packet|codec_type=audio|stream_index=0|pts=460800|pts_time=5.120000|dts=460800|dts_time=5.120000|duration=1800|duration_time=0.020000|size=901|pos=253048|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=460800|pts_time=5.120000|dts=460800|dts_time=5.120000|duration=1800|duration_time=0.020000|size=901|pos=253048|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2a40955c -packet|codec_type=audio|stream_index=0|pts=462600|pts_time=5.140000|dts=462600|dts_time=5.140000|duration=1800|duration_time=0.020000|size=958|pos=254176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=462600|pts_time=5.140000|dts=462600|dts_time=5.140000|duration=1800|duration_time=0.020000|size=958|pos=254176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b46687d4 -packet|codec_type=audio|stream_index=0|pts=464400|pts_time=5.160000|dts=464400|dts_time=5.160000|duration=1800|duration_time=0.020000|size=770|pos=255304|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=464400|pts_time=5.160000|dts=464400|dts_time=5.160000|duration=1800|duration_time=0.020000|size=770|pos=255304|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c4ec89eb -packet|codec_type=audio|stream_index=0|pts=466200|pts_time=5.180000|dts=466200|dts_time=5.180000|duration=1800|duration_time=0.020000|size=773|pos=256244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=466200|pts_time=5.180000|dts=466200|dts_time=5.180000|duration=1800|duration_time=0.020000|size=773|pos=256244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d53fcf9c -packet|codec_type=audio|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=1800|duration_time=0.020000|size=768|pos=257560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=1800|duration_time=0.020000|size=768|pos=257560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:eb9bfc19 -packet|codec_type=audio|stream_index=0|pts=469800|pts_time=5.220000|dts=469800|dts_time=5.220000|duration=1800|duration_time=0.020000|size=776|pos=258500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=469800|pts_time=5.220000|dts=469800|dts_time=5.220000|duration=1800|duration_time=0.020000|size=776|pos=258500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:71e70489 -packet|codec_type=audio|stream_index=0|pts=471600|pts_time=5.240000|dts=471600|dts_time=5.240000|duration=1800|duration_time=0.020000|size=771|pos=259440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=471600|pts_time=5.240000|dts=471600|dts_time=5.240000|duration=1800|duration_time=0.020000|size=771|pos=259440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60a96aca -packet|codec_type=audio|stream_index=0|pts=473400|pts_time=5.260000|dts=473400|dts_time=5.260000|duration=1800|duration_time=0.020000|size=772|pos=260380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=473400|pts_time=5.260000|dts=473400|dts_time=5.260000|duration=1800|duration_time=0.020000|size=772|pos=260380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ceca878e -packet|codec_type=audio|stream_index=0|pts=475200|pts_time=5.280000|dts=475200|dts_time=5.280000|duration=1800|duration_time=0.020000|size=958|pos=261320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=475200|pts_time=5.280000|dts=475200|dts_time=5.280000|duration=1800|duration_time=0.020000|size=958|pos=261320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ab40ffe7 -packet|codec_type=audio|stream_index=0|pts=477000|pts_time=5.300000|dts=477000|dts_time=5.300000|duration=1800|duration_time=0.020000|size=771|pos=262448|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=477000|pts_time=5.300000|dts=477000|dts_time=5.300000|duration=1800|duration_time=0.020000|size=771|pos=262448|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0f8c3162 -packet|codec_type=audio|stream_index=0|pts=478800|pts_time=5.320000|dts=478800|dts_time=5.320000|duration=1800|duration_time=0.020000|size=770|pos=263388|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=478800|pts_time=5.320000|dts=478800|dts_time=5.320000|duration=1800|duration_time=0.020000|size=770|pos=263388|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:af837825 -packet|codec_type=audio|stream_index=0|pts=480600|pts_time=5.340000|dts=480600|dts_time=5.340000|duration=1800|duration_time=0.020000|size=959|pos=264328|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=480600|pts_time=5.340000|dts=480600|dts_time=5.340000|duration=1800|duration_time=0.020000|size=959|pos=264328|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:93a1bea9 -packet|codec_type=audio|stream_index=0|pts=482400|pts_time=5.360000|dts=482400|dts_time=5.360000|duration=1800|duration_time=0.020000|size=769|pos=265456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=482400|pts_time=5.360000|dts=482400|dts_time=5.360000|duration=1800|duration_time=0.020000|size=769|pos=265456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e7289ab0 -packet|codec_type=audio|stream_index=0|pts=484200|pts_time=5.380000|dts=484200|dts_time=5.380000|duration=1800|duration_time=0.020000|size=840|pos=266396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=484200|pts_time=5.380000|dts=484200|dts_time=5.380000|duration=1800|duration_time=0.020000|size=840|pos=266396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4b39626e -packet|codec_type=audio|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=1800|duration_time=0.020000|size=769|pos=267712|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=1800|duration_time=0.020000|size=769|pos=267712|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4bc91d6 -packet|codec_type=audio|stream_index=0|pts=487800|pts_time=5.420000|dts=487800|dts_time=5.420000|duration=1800|duration_time=0.020000|size=767|pos=268652|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=487800|pts_time=5.420000|dts=487800|dts_time=5.420000|duration=1800|duration_time=0.020000|size=767|pos=268652|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:68dd482f -packet|codec_type=audio|stream_index=0|pts=489600|pts_time=5.440000|dts=489600|dts_time=5.440000|duration=1800|duration_time=0.020000|size=951|pos=269592|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=489600|pts_time=5.440000|dts=489600|dts_time=5.440000|duration=1800|duration_time=0.020000|size=951|pos=269592|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:61ab6014 -packet|codec_type=audio|stream_index=0|pts=491400|pts_time=5.460000|dts=491400|dts_time=5.460000|duration=1800|duration_time=0.020000|size=769|pos=270720|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=491400|pts_time=5.460000|dts=491400|dts_time=5.460000|duration=1800|duration_time=0.020000|size=769|pos=270720|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:232f6af8 -packet|codec_type=audio|stream_index=0|pts=493200|pts_time=5.480000|dts=493200|dts_time=5.480000|duration=1800|duration_time=0.020000|size=958|pos=271660|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=493200|pts_time=5.480000|dts=493200|dts_time=5.480000|duration=1800|duration_time=0.020000|size=958|pos=271660|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9a4372e9 -packet|codec_type=audio|stream_index=0|pts=495000|pts_time=5.500000|dts=495000|dts_time=5.500000|duration=1800|duration_time=0.020000|size=773|pos=272788|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=495000|pts_time=5.500000|dts=495000|dts_time=5.500000|duration=1800|duration_time=0.020000|size=773|pos=272788|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f7044435 -packet|codec_type=audio|stream_index=0|pts=496800|pts_time=5.520000|dts=496800|dts_time=5.520000|duration=1800|duration_time=0.020000|size=771|pos=273728|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=496800|pts_time=5.520000|dts=496800|dts_time=5.520000|duration=1800|duration_time=0.020000|size=771|pos=273728|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2d36f75f -packet|codec_type=audio|stream_index=0|pts=498600|pts_time=5.540000|dts=498600|dts_time=5.540000|duration=1800|duration_time=0.020000|size=768|pos=274668|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=498600|pts_time=5.540000|dts=498600|dts_time=5.540000|duration=1800|duration_time=0.020000|size=768|pos=274668|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:11858457 -packet|codec_type=audio|stream_index=0|pts=500400|pts_time=5.560000|dts=500400|dts_time=5.560000|duration=1800|duration_time=0.020000|size=765|pos=275608|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=500400|pts_time=5.560000|dts=500400|dts_time=5.560000|duration=1800|duration_time=0.020000|size=765|pos=275608|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:104cc3b1 -packet|codec_type=audio|stream_index=0|pts=502200|pts_time=5.580000|dts=502200|dts_time=5.580000|duration=1800|duration_time=0.020000|size=774|pos=276548|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=502200|pts_time=5.580000|dts=502200|dts_time=5.580000|duration=1800|duration_time=0.020000|size=774|pos=276548|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8ed3cf9c -packet|codec_type=audio|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=1800|duration_time=0.020000|size=837|pos=277864|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=1800|duration_time=0.020000|size=837|pos=277864|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:16b50427 -packet|codec_type=audio|stream_index=0|pts=505800|pts_time=5.620000|dts=505800|dts_time=5.620000|duration=1800|duration_time=0.020000|size=773|pos=278804|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=505800|pts_time=5.620000|dts=505800|dts_time=5.620000|duration=1800|duration_time=0.020000|size=773|pos=278804|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5c042c3 -packet|codec_type=audio|stream_index=0|pts=507600|pts_time=5.640000|dts=507600|dts_time=5.640000|duration=1800|duration_time=0.020000|size=773|pos=279744|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=507600|pts_time=5.640000|dts=507600|dts_time=5.640000|duration=1800|duration_time=0.020000|size=773|pos=279744|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:722e401f -packet|codec_type=audio|stream_index=0|pts=509400|pts_time=5.660000|dts=509400|dts_time=5.660000|duration=1800|duration_time=0.020000|size=770|pos=280684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=509400|pts_time=5.660000|dts=509400|dts_time=5.660000|duration=1800|duration_time=0.020000|size=770|pos=280684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:831f3604 -packet|codec_type=audio|stream_index=0|pts=511200|pts_time=5.680000|dts=511200|dts_time=5.680000|duration=1800|duration_time=0.020000|size=770|pos=281624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=511200|pts_time=5.680000|dts=511200|dts_time=5.680000|duration=1800|duration_time=0.020000|size=770|pos=281624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7718e73e -packet|codec_type=audio|stream_index=0|pts=513000|pts_time=5.700000|dts=513000|dts_time=5.700000|duration=1800|duration_time=0.020000|size=774|pos=282564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=513000|pts_time=5.700000|dts=513000|dts_time=5.700000|duration=1800|duration_time=0.020000|size=774|pos=282564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:170731a0 -packet|codec_type=audio|stream_index=0|pts=514800|pts_time=5.720000|dts=514800|dts_time=5.720000|duration=1800|duration_time=0.020000|size=767|pos=283504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=514800|pts_time=5.720000|dts=514800|dts_time=5.720000|duration=1800|duration_time=0.020000|size=767|pos=283504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d73c42a8 -packet|codec_type=audio|stream_index=0|pts=516600|pts_time=5.740000|dts=516600|dts_time=5.740000|duration=1800|duration_time=0.020000|size=774|pos=284444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=516600|pts_time=5.740000|dts=516600|dts_time=5.740000|duration=1800|duration_time=0.020000|size=774|pos=284444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:854f9a2e -packet|codec_type=audio|stream_index=0|pts=518400|pts_time=5.760000|dts=518400|dts_time=5.760000|duration=1800|duration_time=0.020000|size=833|pos=285384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=518400|pts_time=5.760000|dts=518400|dts_time=5.760000|duration=1800|duration_time=0.020000|size=833|pos=285384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7d64106d -packet|codec_type=audio|stream_index=0|pts=520200|pts_time=5.780000|dts=520200|dts_time=5.780000|duration=1800|duration_time=0.020000|size=774|pos=286324|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=520200|pts_time=5.780000|dts=520200|dts_time=5.780000|duration=1800|duration_time=0.020000|size=774|pos=286324|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:02e139fa -packet|codec_type=audio|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=1800|duration_time=0.020000|size=768|pos=287640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=1800|duration_time=0.020000|size=768|pos=287640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8b5d5f3b -packet|codec_type=audio|stream_index=0|pts=523800|pts_time=5.820000|dts=523800|dts_time=5.820000|duration=1800|duration_time=0.020000|size=773|pos=288580|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=523800|pts_time=5.820000|dts=523800|dts_time=5.820000|duration=1800|duration_time=0.020000|size=773|pos=288580|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fa25f507 -packet|codec_type=audio|stream_index=0|pts=525600|pts_time=5.840000|dts=525600|dts_time=5.840000|duration=1800|duration_time=0.020000|size=768|pos=289520|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=525600|pts_time=5.840000|dts=525600|dts_time=5.840000|duration=1800|duration_time=0.020000|size=768|pos=289520|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ccbf6593 -packet|codec_type=audio|stream_index=0|pts=527400|pts_time=5.860000|dts=527400|dts_time=5.860000|duration=1800|duration_time=0.020000|size=769|pos=290460|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=527400|pts_time=5.860000|dts=527400|dts_time=5.860000|duration=1800|duration_time=0.020000|size=769|pos=290460|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cea23a52 -packet|codec_type=audio|stream_index=0|pts=529200|pts_time=5.880000|dts=529200|dts_time=5.880000|duration=1800|duration_time=0.020000|size=767|pos=291400|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=529200|pts_time=5.880000|dts=529200|dts_time=5.880000|duration=1800|duration_time=0.020000|size=767|pos=291400|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3ff8eced -packet|codec_type=audio|stream_index=0|pts=531000|pts_time=5.900000|dts=531000|dts_time=5.900000|duration=1800|duration_time=0.020000|size=773|pos=292340|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=531000|pts_time=5.900000|dts=531000|dts_time=5.900000|duration=1800|duration_time=0.020000|size=773|pos=292340|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a5d92bfd -packet|codec_type=audio|stream_index=0|pts=532800|pts_time=5.920000|dts=532800|dts_time=5.920000|duration=1800|duration_time=0.020000|size=774|pos=293280|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=532800|pts_time=5.920000|dts=532800|dts_time=5.920000|duration=1800|duration_time=0.020000|size=774|pos=293280|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:582c9c2e -packet|codec_type=audio|stream_index=0|pts=534600|pts_time=5.940000|dts=534600|dts_time=5.940000|duration=1800|duration_time=0.020000|size=769|pos=294220|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=534600|pts_time=5.940000|dts=534600|dts_time=5.940000|duration=1800|duration_time=0.020000|size=769|pos=294220|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc23f8d9 -packet|codec_type=audio|stream_index=0|pts=536400|pts_time=5.960000|dts=536400|dts_time=5.960000|duration=1800|duration_time=0.020000|size=833|pos=295160|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=536400|pts_time=5.960000|dts=536400|dts_time=5.960000|duration=1800|duration_time=0.020000|size=833|pos=295160|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5b9a2c15 -packet|codec_type=audio|stream_index=0|pts=538200|pts_time=5.980000|dts=538200|dts_time=5.980000|duration=1800|duration_time=0.020000|size=768|pos=296100|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=538200|pts_time=5.980000|dts=538200|dts_time=5.980000|duration=1800|duration_time=0.020000|size=768|pos=296100|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8c48e7c5 -packet|codec_type=audio|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=1800|duration_time=0.020000|size=772|pos=297416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=1800|duration_time=0.020000|size=772|pos=297416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c431b153 -packet|codec_type=audio|stream_index=0|pts=541800|pts_time=6.020000|dts=541800|dts_time=6.020000|duration=1800|duration_time=0.020000|size=839|pos=298356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=541800|pts_time=6.020000|dts=541800|dts_time=6.020000|duration=1800|duration_time=0.020000|size=839|pos=298356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9cfe17d0 -packet|codec_type=audio|stream_index=0|pts=543600|pts_time=6.040000|dts=543600|dts_time=6.040000|duration=1800|duration_time=0.020000|size=769|pos=299296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=543600|pts_time=6.040000|dts=543600|dts_time=6.040000|duration=1800|duration_time=0.020000|size=769|pos=299296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:72510fbb -packet|codec_type=audio|stream_index=0|pts=545400|pts_time=6.060000|dts=545400|dts_time=6.060000|duration=1800|duration_time=0.020000|size=769|pos=300236|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=545400|pts_time=6.060000|dts=545400|dts_time=6.060000|duration=1800|duration_time=0.020000|size=769|pos=300236|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:81830ddd -packet|codec_type=audio|stream_index=0|pts=547200|pts_time=6.080000|dts=547200|dts_time=6.080000|duration=1800|duration_time=0.020000|size=771|pos=301176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=547200|pts_time=6.080000|dts=547200|dts_time=6.080000|duration=1800|duration_time=0.020000|size=771|pos=301176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:43102486 -packet|codec_type=audio|stream_index=0|pts=549000|pts_time=6.100000|dts=549000|dts_time=6.100000|duration=1800|duration_time=0.020000|size=770|pos=302116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=549000|pts_time=6.100000|dts=549000|dts_time=6.100000|duration=1800|duration_time=0.020000|size=770|pos=302116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:49018a2e -packet|codec_type=audio|stream_index=0|pts=550800|pts_time=6.120000|dts=550800|dts_time=6.120000|duration=1800|duration_time=0.020000|size=771|pos=303056|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=550800|pts_time=6.120000|dts=550800|dts_time=6.120000|duration=1800|duration_time=0.020000|size=771|pos=303056|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3a01967a -packet|codec_type=audio|stream_index=0|pts=552600|pts_time=6.140000|dts=552600|dts_time=6.140000|duration=1800|duration_time=0.020000|size=767|pos=303996|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=552600|pts_time=6.140000|dts=552600|dts_time=6.140000|duration=1800|duration_time=0.020000|size=767|pos=303996|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:028a7ab9 -packet|codec_type=audio|stream_index=0|pts=554400|pts_time=6.160000|dts=554400|dts_time=6.160000|duration=1800|duration_time=0.020000|size=899|pos=304936|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=554400|pts_time=6.160000|dts=554400|dts_time=6.160000|duration=1800|duration_time=0.020000|size=899|pos=304936|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:012e3f77 -packet|codec_type=audio|stream_index=0|pts=556200|pts_time=6.180000|dts=556200|dts_time=6.180000|duration=1800|duration_time=0.020000|size=953|pos=305876|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=556200|pts_time=6.180000|dts=556200|dts_time=6.180000|duration=1800|duration_time=0.020000|size=953|pos=305876|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:60935688 -packet|codec_type=audio|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=1800|duration_time=0.020000|size=770|pos=307380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=1800|duration_time=0.020000|size=770|pos=307380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1f54722f -packet|codec_type=audio|stream_index=0|pts=559800|pts_time=6.220000|dts=559800|dts_time=6.220000|duration=1800|duration_time=0.020000|size=770|pos=308320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=559800|pts_time=6.220000|dts=559800|dts_time=6.220000|duration=1800|duration_time=0.020000|size=770|pos=308320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7786349b -packet|codec_type=audio|stream_index=0|pts=561600|pts_time=6.240000|dts=561600|dts_time=6.240000|duration=1800|duration_time=0.020000|size=771|pos=309260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=561600|pts_time=6.240000|dts=561600|dts_time=6.240000|duration=1800|duration_time=0.020000|size=771|pos=309260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1be2464d -packet|codec_type=audio|stream_index=0|pts=563400|pts_time=6.260000|dts=563400|dts_time=6.260000|duration=1800|duration_time=0.020000|size=770|pos=310200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=563400|pts_time=6.260000|dts=563400|dts_time=6.260000|duration=1800|duration_time=0.020000|size=770|pos=310200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cf6b28b9 -packet|codec_type=audio|stream_index=0|pts=565200|pts_time=6.280000|dts=565200|dts_time=6.280000|duration=1800|duration_time=0.020000|size=769|pos=311140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=565200|pts_time=6.280000|dts=565200|dts_time=6.280000|duration=1800|duration_time=0.020000|size=769|pos=311140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:63fa4ab0 -packet|codec_type=audio|stream_index=0|pts=567000|pts_time=6.300000|dts=567000|dts_time=6.300000|duration=1800|duration_time=0.020000|size=896|pos=312080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=567000|pts_time=6.300000|dts=567000|dts_time=6.300000|duration=1800|duration_time=0.020000|size=896|pos=312080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:06a8e324 -packet|codec_type=audio|stream_index=0|pts=568800|pts_time=6.320000|dts=568800|dts_time=6.320000|duration=1800|duration_time=0.020000|size=957|pos=313020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=568800|pts_time=6.320000|dts=568800|dts_time=6.320000|duration=1800|duration_time=0.020000|size=957|pos=313020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c37f55e9 -packet|codec_type=audio|stream_index=0|pts=570600|pts_time=6.340000|dts=570600|dts_time=6.340000|duration=1800|duration_time=0.020000|size=773|pos=314148|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=570600|pts_time=6.340000|dts=570600|dts_time=6.340000|duration=1800|duration_time=0.020000|size=773|pos=314148|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:82f8ac84 -packet|codec_type=audio|stream_index=0|pts=572400|pts_time=6.360000|dts=572400|dts_time=6.360000|duration=1800|duration_time=0.020000|size=774|pos=315088|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=572400|pts_time=6.360000|dts=572400|dts_time=6.360000|duration=1800|duration_time=0.020000|size=774|pos=315088|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3ed82724 -packet|codec_type=audio|stream_index=0|pts=574200|pts_time=6.380000|dts=574200|dts_time=6.380000|duration=1800|duration_time=0.020000|size=956|pos=316028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=574200|pts_time=6.380000|dts=574200|dts_time=6.380000|duration=1800|duration_time=0.020000|size=956|pos=316028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ed21dfec -packet|codec_type=audio|stream_index=0|pts=576000|pts_time=6.400000|dts=576000|dts_time=6.400000|duration=1800|duration_time=0.020000|size=768|pos=317532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=576000|pts_time=6.400000|dts=576000|dts_time=6.400000|duration=1800|duration_time=0.020000|size=768|pos=317532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ef20c09c -packet|codec_type=audio|stream_index=0|pts=577800|pts_time=6.420000|dts=577800|dts_time=6.420000|duration=1800|duration_time=0.020000|size=770|pos=318472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=577800|pts_time=6.420000|dts=577800|dts_time=6.420000|duration=1800|duration_time=0.020000|size=770|pos=318472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5f72438e -packet|codec_type=audio|stream_index=0|pts=579600|pts_time=6.440000|dts=579600|dts_time=6.440000|duration=1800|duration_time=0.020000|size=771|pos=319412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=579600|pts_time=6.440000|dts=579600|dts_time=6.440000|duration=1800|duration_time=0.020000|size=771|pos=319412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:831f56d5 -packet|codec_type=audio|stream_index=0|pts=581400|pts_time=6.460000|dts=581400|dts_time=6.460000|duration=1800|duration_time=0.020000|size=955|pos=320352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=581400|pts_time=6.460000|dts=581400|dts_time=6.460000|duration=1800|duration_time=0.020000|size=955|pos=320352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a3fb153b -packet|codec_type=audio|stream_index=0|pts=583200|pts_time=6.480000|dts=583200|dts_time=6.480000|duration=1800|duration_time=0.020000|size=953|pos=321480|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=583200|pts_time=6.480000|dts=583200|dts_time=6.480000|duration=1800|duration_time=0.020000|size=953|pos=321480|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:109825ac -packet|codec_type=audio|stream_index=0|pts=585000|pts_time=6.500000|dts=585000|dts_time=6.500000|duration=1800|duration_time=0.020000|size=767|pos=322608|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=585000|pts_time=6.500000|dts=585000|dts_time=6.500000|duration=1800|duration_time=0.020000|size=767|pos=322608|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5cb97953 -packet|codec_type=audio|stream_index=0|pts=586800|pts_time=6.520000|dts=586800|dts_time=6.520000|duration=1800|duration_time=0.020000|size=768|pos=323548|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=586800|pts_time=6.520000|dts=586800|dts_time=6.520000|duration=1800|duration_time=0.020000|size=768|pos=323548|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:9aa43658 -packet|codec_type=audio|stream_index=0|pts=588600|pts_time=6.540000|dts=588600|dts_time=6.540000|duration=1800|duration_time=0.020000|size=774|pos=324488|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=588600|pts_time=6.540000|dts=588600|dts_time=6.540000|duration=1800|duration_time=0.020000|size=774|pos=324488|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ccad3c6 -packet|codec_type=audio|stream_index=0|pts=590400|pts_time=6.560000|dts=590400|dts_time=6.560000|duration=1800|duration_time=0.020000|size=835|pos=325428|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=590400|pts_time=6.560000|dts=590400|dts_time=6.560000|duration=1800|duration_time=0.020000|size=835|pos=325428|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee1e951f -packet|codec_type=audio|stream_index=0|pts=592200|pts_time=6.580000|dts=592200|dts_time=6.580000|duration=1800|duration_time=0.020000|size=768|pos=326368|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=592200|pts_time=6.580000|dts=592200|dts_time=6.580000|duration=1800|duration_time=0.020000|size=768|pos=326368|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7e964664 -packet|codec_type=audio|stream_index=0|pts=594000|pts_time=6.600000|dts=594000|dts_time=6.600000|duration=1800|duration_time=0.020000|size=769|pos=327684|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=594000|pts_time=6.600000|dts=594000|dts_time=6.600000|duration=1800|duration_time=0.020000|size=769|pos=327684|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:46489e72 -packet|codec_type=audio|stream_index=0|pts=595800|pts_time=6.620000|dts=595800|dts_time=6.620000|duration=1800|duration_time=0.020000|size=771|pos=328624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=595800|pts_time=6.620000|dts=595800|dts_time=6.620000|duration=1800|duration_time=0.020000|size=771|pos=328624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:528f881d -packet|codec_type=audio|stream_index=0|pts=597600|pts_time=6.640000|dts=597600|dts_time=6.640000|duration=1800|duration_time=0.020000|size=771|pos=329564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=597600|pts_time=6.640000|dts=597600|dts_time=6.640000|duration=1800|duration_time=0.020000|size=771|pos=329564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e776ddf8 -packet|codec_type=audio|stream_index=0|pts=599400|pts_time=6.660000|dts=599400|dts_time=6.660000|duration=1800|duration_time=0.020000|size=770|pos=330504|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=599400|pts_time=6.660000|dts=599400|dts_time=6.660000|duration=1800|duration_time=0.020000|size=770|pos=330504|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f4d9468d -packet|codec_type=audio|stream_index=0|pts=601200|pts_time=6.680000|dts=601200|dts_time=6.680000|duration=1800|duration_time=0.020000|size=768|pos=331444|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=601200|pts_time=6.680000|dts=601200|dts_time=6.680000|duration=1800|duration_time=0.020000|size=768|pos=331444|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0b5bc3e0 -packet|codec_type=audio|stream_index=0|pts=603000|pts_time=6.700000|dts=603000|dts_time=6.700000|duration=1800|duration_time=0.020000|size=951|pos=332384|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=603000|pts_time=6.700000|dts=603000|dts_time=6.700000|duration=1800|duration_time=0.020000|size=951|pos=332384|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4c6d023d -packet|codec_type=audio|stream_index=0|pts=604800|pts_time=6.720000|dts=604800|dts_time=6.720000|duration=1800|duration_time=0.020000|size=950|pos=333512|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=604800|pts_time=6.720000|dts=604800|dts_time=6.720000|duration=1800|duration_time=0.020000|size=950|pos=333512|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:29588833 -packet|codec_type=audio|stream_index=0|pts=606600|pts_time=6.740000|dts=606600|dts_time=6.740000|duration=1800|duration_time=0.020000|size=947|pos=334640|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=606600|pts_time=6.740000|dts=606600|dts_time=6.740000|duration=1800|duration_time=0.020000|size=947|pos=334640|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12f446a5 -packet|codec_type=audio|stream_index=0|pts=608400|pts_time=6.760000|dts=608400|dts_time=6.760000|duration=1800|duration_time=0.020000|size=956|pos=335768|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=608400|pts_time=6.760000|dts=608400|dts_time=6.760000|duration=1800|duration_time=0.020000|size=956|pos=335768|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:39a765b6 -packet|codec_type=audio|stream_index=0|pts=610200|pts_time=6.780000|dts=610200|dts_time=6.780000|duration=1800|duration_time=0.020000|size=951|pos=336896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=610200|pts_time=6.780000|dts=610200|dts_time=6.780000|duration=1800|duration_time=0.020000|size=951|pos=336896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:79ab4162 -packet|codec_type=audio|stream_index=0|pts=612000|pts_time=6.800000|dts=612000|dts_time=6.800000|duration=1800|duration_time=0.020000|size=943|pos=338400|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=612000|pts_time=6.800000|dts=612000|dts_time=6.800000|duration=1800|duration_time=0.020000|size=943|pos=338400|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1c20d61c -packet|codec_type=audio|stream_index=0|pts=613800|pts_time=6.820000|dts=613800|dts_time=6.820000|duration=1800|duration_time=0.020000|size=766|pos=339528|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=613800|pts_time=6.820000|dts=613800|dts_time=6.820000|duration=1800|duration_time=0.020000|size=766|pos=339528|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0e5d1ee5 -packet|codec_type=audio|stream_index=0|pts=615600|pts_time=6.840000|dts=615600|dts_time=6.840000|duration=1800|duration_time=0.020000|size=890|pos=340468|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=615600|pts_time=6.840000|dts=615600|dts_time=6.840000|duration=1800|duration_time=0.020000|size=890|pos=340468|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:27c19b26 -packet|codec_type=audio|stream_index=0|pts=617400|pts_time=6.860000|dts=617400|dts_time=6.860000|duration=1800|duration_time=0.020000|size=952|pos=341408|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=617400|pts_time=6.860000|dts=617400|dts_time=6.860000|duration=1800|duration_time=0.020000|size=952|pos=341408|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8ba8ff4c -packet|codec_type=audio|stream_index=0|pts=619200|pts_time=6.880000|dts=619200|dts_time=6.880000|duration=1800|duration_time=0.020000|size=766|pos=342536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=619200|pts_time=6.880000|dts=619200|dts_time=6.880000|duration=1800|duration_time=0.020000|size=766|pos=342536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:61b51e53 -packet|codec_type=audio|stream_index=0|pts=621000|pts_time=6.900000|dts=621000|dts_time=6.900000|duration=1800|duration_time=0.020000|size=767|pos=343476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=621000|pts_time=6.900000|dts=621000|dts_time=6.900000|duration=1800|duration_time=0.020000|size=767|pos=343476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:223fd4b8 -packet|codec_type=audio|stream_index=0|pts=622800|pts_time=6.920000|dts=622800|dts_time=6.920000|duration=1800|duration_time=0.020000|size=760|pos=344416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=622800|pts_time=6.920000|dts=622800|dts_time=6.920000|duration=1800|duration_time=0.020000|size=760|pos=344416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:221e6f8a -packet|codec_type=audio|stream_index=0|pts=624600|pts_time=6.940000|dts=624600|dts_time=6.940000|duration=1800|duration_time=0.020000|size=946|pos=345356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=624600|pts_time=6.940000|dts=624600|dts_time=6.940000|duration=1800|duration_time=0.020000|size=946|pos=345356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:623d901e -packet|codec_type=audio|stream_index=0|pts=626400|pts_time=6.960000|dts=626400|dts_time=6.960000|duration=1800|duration_time=0.020000|size=769|pos=346484|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=626400|pts_time=6.960000|dts=626400|dts_time=6.960000|duration=1800|duration_time=0.020000|size=769|pos=346484|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:584cd53d -packet|codec_type=audio|stream_index=0|pts=628200|pts_time=6.980000|dts=628200|dts_time=6.980000|duration=1800|duration_time=0.020000|size=760|pos=347424|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=628200|pts_time=6.980000|dts=628200|dts_time=6.980000|duration=1800|duration_time=0.020000|size=760|pos=347424|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:179b3137 -packet|codec_type=audio|stream_index=0|pts=630000|pts_time=7.000000|dts=630000|dts_time=7.000000|duration=1800|duration_time=0.020000|size=762|pos=348740|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=630000|pts_time=7.000000|dts=630000|dts_time=7.000000|duration=1800|duration_time=0.020000|size=762|pos=348740|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e0e617f2 -packet|codec_type=audio|stream_index=0|pts=631800|pts_time=7.020000|dts=631800|dts_time=7.020000|duration=1800|duration_time=0.020000|size=767|pos=349680|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=631800|pts_time=7.020000|dts=631800|dts_time=7.020000|duration=1800|duration_time=0.020000|size=767|pos=349680|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:560639a0 -packet|codec_type=audio|stream_index=0|pts=633600|pts_time=7.040000|dts=633600|dts_time=7.040000|duration=1800|duration_time=0.020000|size=767|pos=350620|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=633600|pts_time=7.040000|dts=633600|dts_time=7.040000|duration=1800|duration_time=0.020000|size=767|pos=350620|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a88ea02f -packet|codec_type=audio|stream_index=0|pts=635400|pts_time=7.060000|dts=635400|dts_time=7.060000|duration=1800|duration_time=0.020000|size=763|pos=351560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=635400|pts_time=7.060000|dts=635400|dts_time=7.060000|duration=1800|duration_time=0.020000|size=763|pos=351560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6a9f391f -packet|codec_type=audio|stream_index=0|pts=637200|pts_time=7.080000|dts=637200|dts_time=7.080000|duration=1800|duration_time=0.020000|size=760|pos=352500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=637200|pts_time=7.080000|dts=637200|dts_time=7.080000|duration=1800|duration_time=0.020000|size=760|pos=352500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:217730ab -packet|codec_type=audio|stream_index=0|pts=639000|pts_time=7.100000|dts=639000|dts_time=7.100000|duration=1800|duration_time=0.020000|size=763|pos=353440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=639000|pts_time=7.100000|dts=639000|dts_time=7.100000|duration=1800|duration_time=0.020000|size=763|pos=353440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ffa59273 -packet|codec_type=audio|stream_index=0|pts=640800|pts_time=7.120000|dts=640800|dts_time=7.120000|duration=1800|duration_time=0.020000|size=764|pos=354380|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=640800|pts_time=7.120000|dts=640800|dts_time=7.120000|duration=1800|duration_time=0.020000|size=764|pos=354380|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:05a70a45 -packet|codec_type=audio|stream_index=0|pts=642600|pts_time=7.140000|dts=642600|dts_time=7.140000|duration=1800|duration_time=0.020000|size=764|pos=355320|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=642600|pts_time=7.140000|dts=642600|dts_time=7.140000|duration=1800|duration_time=0.020000|size=764|pos=355320|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1e2e4d40 -packet|codec_type=audio|stream_index=0|pts=644400|pts_time=7.160000|dts=644400|dts_time=7.160000|duration=1800|duration_time=0.020000|size=763|pos=356260|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=644400|pts_time=7.160000|dts=644400|dts_time=7.160000|duration=1800|duration_time=0.020000|size=763|pos=356260|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:695b9d24 -packet|codec_type=audio|stream_index=0|pts=646200|pts_time=7.180000|dts=646200|dts_time=7.180000|duration=1800|duration_time=0.020000|size=763|pos=357200|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=646200|pts_time=7.180000|dts=646200|dts_time=7.180000|duration=1800|duration_time=0.020000|size=763|pos=357200|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:007b90ce -packet|codec_type=audio|stream_index=0|pts=648000|pts_time=7.200000|dts=648000|dts_time=7.200000|duration=1800|duration_time=0.020000|size=764|pos=358516|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=648000|pts_time=7.200000|dts=648000|dts_time=7.200000|duration=1800|duration_time=0.020000|size=764|pos=358516|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:188da6de -packet|codec_type=audio|stream_index=0|pts=649800|pts_time=7.220000|dts=649800|dts_time=7.220000|duration=1800|duration_time=0.020000|size=766|pos=359456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=649800|pts_time=7.220000|dts=649800|dts_time=7.220000|duration=1800|duration_time=0.020000|size=766|pos=359456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1046d54c -packet|codec_type=audio|stream_index=0|pts=651600|pts_time=7.240000|dts=651600|dts_time=7.240000|duration=1800|duration_time=0.020000|size=767|pos=360396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=651600|pts_time=7.240000|dts=651600|dts_time=7.240000|duration=1800|duration_time=0.020000|size=767|pos=360396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:aa450d3d -packet|codec_type=audio|stream_index=0|pts=653400|pts_time=7.260000|dts=653400|dts_time=7.260000|duration=1800|duration_time=0.020000|size=765|pos=361336|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=653400|pts_time=7.260000|dts=653400|dts_time=7.260000|duration=1800|duration_time=0.020000|size=765|pos=361336|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:80bb936b -packet|codec_type=audio|stream_index=0|pts=655200|pts_time=7.280000|dts=655200|dts_time=7.280000|duration=1800|duration_time=0.020000|size=767|pos=362276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=655200|pts_time=7.280000|dts=655200|dts_time=7.280000|duration=1800|duration_time=0.020000|size=767|pos=362276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:47bc2556 -packet|codec_type=audio|stream_index=0|pts=657000|pts_time=7.300000|dts=657000|dts_time=7.300000|duration=1800|duration_time=0.020000|size=763|pos=363216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=657000|pts_time=7.300000|dts=657000|dts_time=7.300000|duration=1800|duration_time=0.020000|size=763|pos=363216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:97d4c99c -packet|codec_type=audio|stream_index=0|pts=658800|pts_time=7.320000|dts=658800|dts_time=7.320000|duration=1800|duration_time=0.020000|size=767|pos=364156|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=658800|pts_time=7.320000|dts=658800|dts_time=7.320000|duration=1800|duration_time=0.020000|size=767|pos=364156|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:37252d43 -packet|codec_type=audio|stream_index=0|pts=660600|pts_time=7.340000|dts=660600|dts_time=7.340000|duration=1800|duration_time=0.020000|size=768|pos=365096|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=660600|pts_time=7.340000|dts=660600|dts_time=7.340000|duration=1800|duration_time=0.020000|size=768|pos=365096|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:76918244 -packet|codec_type=audio|stream_index=0|pts=662400|pts_time=7.360000|dts=662400|dts_time=7.360000|duration=1800|duration_time=0.020000|size=764|pos=366036|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=662400|pts_time=7.360000|dts=662400|dts_time=7.360000|duration=1800|duration_time=0.020000|size=764|pos=366036|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ba0d5d3 -packet|codec_type=audio|stream_index=0|pts=664200|pts_time=7.380000|dts=664200|dts_time=7.380000|duration=1800|duration_time=0.020000|size=765|pos=366976|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=664200|pts_time=7.380000|dts=664200|dts_time=7.380000|duration=1800|duration_time=0.020000|size=765|pos=366976|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5b2b81f0 -packet|codec_type=audio|stream_index=0|pts=666000|pts_time=7.400000|dts=666000|dts_time=7.400000|duration=1800|duration_time=0.020000|size=764|pos=368292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=666000|pts_time=7.400000|dts=666000|dts_time=7.400000|duration=1800|duration_time=0.020000|size=764|pos=368292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:161f0b38 -packet|codec_type=audio|stream_index=0|pts=667800|pts_time=7.420000|dts=667800|dts_time=7.420000|duration=1800|duration_time=0.020000|size=769|pos=369232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=667800|pts_time=7.420000|dts=667800|dts_time=7.420000|duration=1800|duration_time=0.020000|size=769|pos=369232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:78b4530b -packet|codec_type=audio|stream_index=0|pts=669600|pts_time=7.440000|dts=669600|dts_time=7.440000|duration=1800|duration_time=0.020000|size=766|pos=370172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=669600|pts_time=7.440000|dts=669600|dts_time=7.440000|duration=1800|duration_time=0.020000|size=766|pos=370172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0844a4f -packet|codec_type=audio|stream_index=0|pts=671400|pts_time=7.460000|dts=671400|dts_time=7.460000|duration=1800|duration_time=0.020000|size=766|pos=371112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=671400|pts_time=7.460000|dts=671400|dts_time=7.460000|duration=1800|duration_time=0.020000|size=766|pos=371112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09ef7940 -packet|codec_type=audio|stream_index=0|pts=673200|pts_time=7.480000|dts=673200|dts_time=7.480000|duration=1800|duration_time=0.020000|size=829|pos=372052|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=673200|pts_time=7.480000|dts=673200|dts_time=7.480000|duration=1800|duration_time=0.020000|size=829|pos=372052|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:053ff4c6 -packet|codec_type=audio|stream_index=0|pts=675000|pts_time=7.500000|dts=675000|dts_time=7.500000|duration=1800|duration_time=0.020000|size=765|pos=372992|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=675000|pts_time=7.500000|dts=675000|dts_time=7.500000|duration=1800|duration_time=0.020000|size=765|pos=372992|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:dffb6a19 -packet|codec_type=audio|stream_index=0|pts=676800|pts_time=7.520000|dts=676800|dts_time=7.520000|duration=1800|duration_time=0.020000|size=766|pos=373932|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=676800|pts_time=7.520000|dts=676800|dts_time=7.520000|duration=1800|duration_time=0.020000|size=766|pos=373932|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:95240406 -packet|codec_type=audio|stream_index=0|pts=678600|pts_time=7.540000|dts=678600|dts_time=7.540000|duration=1800|duration_time=0.020000|size=766|pos=374872|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=678600|pts_time=7.540000|dts=678600|dts_time=7.540000|duration=1800|duration_time=0.020000|size=766|pos=374872|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e2e8f563 -packet|codec_type=audio|stream_index=0|pts=680400|pts_time=7.560000|dts=680400|dts_time=7.560000|duration=1800|duration_time=0.020000|size=898|pos=375812|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=680400|pts_time=7.560000|dts=680400|dts_time=7.560000|duration=1800|duration_time=0.020000|size=898|pos=375812|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c1c53334 -packet|codec_type=audio|stream_index=0|pts=682200|pts_time=7.580000|dts=682200|dts_time=7.580000|duration=1800|duration_time=0.020000|size=767|pos=376940|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=682200|pts_time=7.580000|dts=682200|dts_time=7.580000|duration=1800|duration_time=0.020000|size=767|pos=376940|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f122e957 -packet|codec_type=audio|stream_index=0|pts=684000|pts_time=7.600000|dts=684000|dts_time=7.600000|duration=1800|duration_time=0.020000|size=896|pos=378256|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=684000|pts_time=7.600000|dts=684000|dts_time=7.600000|duration=1800|duration_time=0.020000|size=896|pos=378256|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cd022652 -packet|codec_type=audio|stream_index=0|pts=685800|pts_time=7.620000|dts=685800|dts_time=7.620000|duration=1800|duration_time=0.020000|size=764|pos=379196|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=685800|pts_time=7.620000|dts=685800|dts_time=7.620000|duration=1800|duration_time=0.020000|size=764|pos=379196|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:909c400c -packet|codec_type=audio|stream_index=0|pts=687600|pts_time=7.640000|dts=687600|dts_time=7.640000|duration=1800|duration_time=0.020000|size=762|pos=380136|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=687600|pts_time=7.640000|dts=687600|dts_time=7.640000|duration=1800|duration_time=0.020000|size=762|pos=380136|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7340fb8d -packet|codec_type=audio|stream_index=0|pts=689400|pts_time=7.660000|dts=689400|dts_time=7.660000|duration=1800|duration_time=0.020000|size=762|pos=381076|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=689400|pts_time=7.660000|dts=689400|dts_time=7.660000|duration=1800|duration_time=0.020000|size=762|pos=381076|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:46b59223 -packet|codec_type=audio|stream_index=0|pts=691200|pts_time=7.680000|dts=691200|dts_time=7.680000|duration=1800|duration_time=0.020000|size=763|pos=382016|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=691200|pts_time=7.680000|dts=691200|dts_time=7.680000|duration=1800|duration_time=0.020000|size=763|pos=382016|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2f1ebb7e -packet|codec_type=audio|stream_index=0|pts=693000|pts_time=7.700000|dts=693000|dts_time=7.700000|duration=1800|duration_time=0.020000|size=947|pos=382956|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=693000|pts_time=7.700000|dts=693000|dts_time=7.700000|duration=1800|duration_time=0.020000|size=947|pos=382956|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b56bee4b -packet|codec_type=audio|stream_index=0|pts=694800|pts_time=7.720000|dts=694800|dts_time=7.720000|duration=1800|duration_time=0.020000|size=767|pos=384084|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=694800|pts_time=7.720000|dts=694800|dts_time=7.720000|duration=1800|duration_time=0.020000|size=767|pos=384084|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:57c778a9 -packet|codec_type=audio|stream_index=0|pts=696600|pts_time=7.740000|dts=696600|dts_time=7.740000|duration=1800|duration_time=0.020000|size=957|pos=385024|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=696600|pts_time=7.740000|dts=696600|dts_time=7.740000|duration=1800|duration_time=0.020000|size=957|pos=385024|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:599b6964 -packet|codec_type=audio|stream_index=0|pts=698400|pts_time=7.760000|dts=698400|dts_time=7.760000|duration=1800|duration_time=0.020000|size=955|pos=386152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=698400|pts_time=7.760000|dts=698400|dts_time=7.760000|duration=1800|duration_time=0.020000|size=955|pos=386152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2351bfa3 -packet|codec_type=audio|stream_index=0|pts=700200|pts_time=7.780000|dts=700200|dts_time=7.780000|duration=1800|duration_time=0.020000|size=767|pos=387280|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=700200|pts_time=7.780000|dts=700200|dts_time=7.780000|duration=1800|duration_time=0.020000|size=767|pos=387280|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f31f5d14 -packet|codec_type=audio|stream_index=0|pts=702000|pts_time=7.800000|dts=702000|dts_time=7.800000|duration=1800|duration_time=0.020000|size=767|pos=388596|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=702000|pts_time=7.800000|dts=702000|dts_time=7.800000|duration=1800|duration_time=0.020000|size=767|pos=388596|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c0f7f4b5 -packet|codec_type=audio|stream_index=0|pts=703800|pts_time=7.820000|dts=703800|dts_time=7.820000|duration=1800|duration_time=0.020000|size=764|pos=389536|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=703800|pts_time=7.820000|dts=703800|dts_time=7.820000|duration=1800|duration_time=0.020000|size=764|pos=389536|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f321de8a -packet|codec_type=audio|stream_index=0|pts=705600|pts_time=7.840000|dts=705600|dts_time=7.840000|duration=1800|duration_time=0.020000|size=763|pos=390476|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=705600|pts_time=7.840000|dts=705600|dts_time=7.840000|duration=1800|duration_time=0.020000|size=763|pos=390476|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:64e7e790 -packet|codec_type=audio|stream_index=0|pts=707400|pts_time=7.860000|dts=707400|dts_time=7.860000|duration=1800|duration_time=0.020000|size=769|pos=391416|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=707400|pts_time=7.860000|dts=707400|dts_time=7.860000|duration=1800|duration_time=0.020000|size=769|pos=391416|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9bef93e -packet|codec_type=audio|stream_index=0|pts=709200|pts_time=7.880000|dts=709200|dts_time=7.880000|duration=1800|duration_time=0.020000|size=766|pos=392356|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=709200|pts_time=7.880000|dts=709200|dts_time=7.880000|duration=1800|duration_time=0.020000|size=766|pos=392356|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b08e677b -packet|codec_type=audio|stream_index=0|pts=711000|pts_time=7.900000|dts=711000|dts_time=7.900000|duration=1800|duration_time=0.020000|size=762|pos=393296|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=711000|pts_time=7.900000|dts=711000|dts_time=7.900000|duration=1800|duration_time=0.020000|size=762|pos=393296|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc2d57f3 -packet|codec_type=audio|stream_index=0|pts=712800|pts_time=7.920000|dts=712800|dts_time=7.920000|duration=1800|duration_time=0.020000|size=766|pos=394236|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=712800|pts_time=7.920000|dts=712800|dts_time=7.920000|duration=1800|duration_time=0.020000|size=766|pos=394236|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:920b310d -packet|codec_type=audio|stream_index=0|pts=714600|pts_time=7.940000|dts=714600|dts_time=7.940000|duration=1800|duration_time=0.020000|size=768|pos=395176|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=714600|pts_time=7.940000|dts=714600|dts_time=7.940000|duration=1800|duration_time=0.020000|size=768|pos=395176|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7547a71e -packet|codec_type=audio|stream_index=0|pts=716400|pts_time=7.960000|dts=716400|dts_time=7.960000|duration=1800|duration_time=0.020000|size=765|pos=396116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=716400|pts_time=7.960000|dts=716400|dts_time=7.960000|duration=1800|duration_time=0.020000|size=765|pos=396116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6d0f72a9 -packet|codec_type=audio|stream_index=0|pts=718200|pts_time=7.980000|dts=718200|dts_time=7.980000|duration=1800|duration_time=0.020000|size=953|pos=397056|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=718200|pts_time=7.980000|dts=718200|dts_time=7.980000|duration=1800|duration_time=0.020000|size=953|pos=397056|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6daae92b -packet|codec_type=audio|stream_index=0|pts=720000|pts_time=8.000000|dts=720000|dts_time=8.000000|duration=1800|duration_time=0.020000|size=769|pos=398560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=720000|pts_time=8.000000|dts=720000|dts_time=8.000000|duration=1800|duration_time=0.020000|size=769|pos=398560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8bd8704e -packet|codec_type=audio|stream_index=0|pts=721800|pts_time=8.020000|dts=721800|dts_time=8.020000|duration=1800|duration_time=0.020000|size=955|pos=399500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=721800|pts_time=8.020000|dts=721800|dts_time=8.020000|duration=1800|duration_time=0.020000|size=955|pos=399500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:111f49de -packet|codec_type=audio|stream_index=0|pts=723600|pts_time=8.040000|dts=723600|dts_time=8.040000|duration=1800|duration_time=0.020000|size=952|pos=400628|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=723600|pts_time=8.040000|dts=723600|dts_time=8.040000|duration=1800|duration_time=0.020000|size=952|pos=400628|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6e266d5 -packet|codec_type=audio|stream_index=0|pts=725400|pts_time=8.060000|dts=725400|dts_time=8.060000|duration=1800|duration_time=0.020000|size=951|pos=401756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=725400|pts_time=8.060000|dts=725400|dts_time=8.060000|duration=1800|duration_time=0.020000|size=951|pos=401756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b0f5283f -packet|codec_type=audio|stream_index=0|pts=727200|pts_time=8.080000|dts=727200|dts_time=8.080000|duration=1800|duration_time=0.020000|size=954|pos=402884|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=727200|pts_time=8.080000|dts=727200|dts_time=8.080000|duration=1800|duration_time=0.020000|size=954|pos=402884|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f70d4475 -packet|codec_type=audio|stream_index=0|pts=729000|pts_time=8.100000|dts=729000|dts_time=8.100000|duration=1800|duration_time=0.020000|size=948|pos=404012|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=729000|pts_time=8.100000|dts=729000|dts_time=8.100000|duration=1800|duration_time=0.020000|size=948|pos=404012|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:371078df -packet|codec_type=audio|stream_index=0|pts=730800|pts_time=8.120000|dts=730800|dts_time=8.120000|duration=1800|duration_time=0.020000|size=761|pos=405140|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=730800|pts_time=8.120000|dts=730800|dts_time=8.120000|duration=1800|duration_time=0.020000|size=761|pos=405140|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c2aa814b -packet|codec_type=audio|stream_index=0|pts=732600|pts_time=8.140000|dts=732600|dts_time=8.140000|duration=1800|duration_time=0.020000|size=763|pos=406080|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=732600|pts_time=8.140000|dts=732600|dts_time=8.140000|duration=1800|duration_time=0.020000|size=763|pos=406080|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:188194bc -packet|codec_type=audio|stream_index=0|pts=734400|pts_time=8.160000|dts=734400|dts_time=8.160000|duration=1800|duration_time=0.020000|size=760|pos=407020|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=734400|pts_time=8.160000|dts=734400|dts_time=8.160000|duration=1800|duration_time=0.020000|size=760|pos=407020|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:982ba78c -packet|codec_type=audio|stream_index=0|pts=736200|pts_time=8.180000|dts=736200|dts_time=8.180000|duration=1800|duration_time=0.020000|size=764|pos=407960|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=736200|pts_time=8.180000|dts=736200|dts_time=8.180000|duration=1800|duration_time=0.020000|size=764|pos=407960|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bf244c73 -packet|codec_type=audio|stream_index=0|pts=738000|pts_time=8.200000|dts=738000|dts_time=8.200000|duration=1800|duration_time=0.020000|size=764|pos=409276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=738000|pts_time=8.200000|dts=738000|dts_time=8.200000|duration=1800|duration_time=0.020000|size=764|pos=409276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8bdf82ed -packet|codec_type=audio|stream_index=0|pts=739800|pts_time=8.220000|dts=739800|dts_time=8.220000|duration=1800|duration_time=0.020000|size=946|pos=410216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=739800|pts_time=8.220000|dts=739800|dts_time=8.220000|duration=1800|duration_time=0.020000|size=946|pos=410216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:acb2d4f3 -packet|codec_type=audio|stream_index=0|pts=741600|pts_time=8.240000|dts=741600|dts_time=8.240000|duration=1800|duration_time=0.020000|size=758|pos=411344|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=741600|pts_time=8.240000|dts=741600|dts_time=8.240000|duration=1800|duration_time=0.020000|size=758|pos=411344|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1cefab3c -packet|codec_type=audio|stream_index=0|pts=743400|pts_time=8.260000|dts=743400|dts_time=8.260000|duration=1800|duration_time=0.020000|size=950|pos=412284|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=743400|pts_time=8.260000|dts=743400|dts_time=8.260000|duration=1800|duration_time=0.020000|size=950|pos=412284|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0bd02594 -packet|codec_type=audio|stream_index=0|pts=745200|pts_time=8.280000|dts=745200|dts_time=8.280000|duration=1800|duration_time=0.020000|size=769|pos=413412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=745200|pts_time=8.280000|dts=745200|dts_time=8.280000|duration=1800|duration_time=0.020000|size=769|pos=413412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc6fff1d -packet|codec_type=audio|stream_index=0|pts=747000|pts_time=8.300000|dts=747000|dts_time=8.300000|duration=1800|duration_time=0.020000|size=764|pos=414352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=747000|pts_time=8.300000|dts=747000|dts_time=8.300000|duration=1800|duration_time=0.020000|size=764|pos=414352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cb2fc3d9 -packet|codec_type=audio|stream_index=0|pts=748800|pts_time=8.320000|dts=748800|dts_time=8.320000|duration=1800|duration_time=0.020000|size=757|pos=415292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=748800|pts_time=8.320000|dts=748800|dts_time=8.320000|duration=1800|duration_time=0.020000|size=757|pos=415292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:860da403 -packet|codec_type=audio|stream_index=0|pts=750600|pts_time=8.340000|dts=750600|dts_time=8.340000|duration=1800|duration_time=0.020000|size=761|pos=416232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=750600|pts_time=8.340000|dts=750600|dts_time=8.340000|duration=1800|duration_time=0.020000|size=761|pos=416232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:14aca2c6 -packet|codec_type=audio|stream_index=0|pts=752400|pts_time=8.360000|dts=752400|dts_time=8.360000|duration=1800|duration_time=0.020000|size=761|pos=417172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=752400|pts_time=8.360000|dts=752400|dts_time=8.360000|duration=1800|duration_time=0.020000|size=761|pos=417172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c5d24ee7 -packet|codec_type=audio|stream_index=0|pts=754200|pts_time=8.380000|dts=754200|dts_time=8.380000|duration=1800|duration_time=0.020000|size=759|pos=418112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=754200|pts_time=8.380000|dts=754200|dts_time=8.380000|duration=1800|duration_time=0.020000|size=759|pos=418112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:91680f09 -packet|codec_type=audio|stream_index=0|pts=756000|pts_time=8.400000|dts=756000|dts_time=8.400000|duration=1800|duration_time=0.020000|size=758|pos=419428|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=756000|pts_time=8.400000|dts=756000|dts_time=8.400000|duration=1800|duration_time=0.020000|size=758|pos=419428|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c6b2948d -packet|codec_type=audio|stream_index=0|pts=757800|pts_time=8.420000|dts=757800|dts_time=8.420000|duration=1800|duration_time=0.020000|size=767|pos=420368|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=757800|pts_time=8.420000|dts=757800|dts_time=8.420000|duration=1800|duration_time=0.020000|size=767|pos=420368|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:20ff251c -packet|codec_type=audio|stream_index=0|pts=759600|pts_time=8.440000|dts=759600|dts_time=8.440000|duration=1800|duration_time=0.020000|size=761|pos=421308|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=759600|pts_time=8.440000|dts=759600|dts_time=8.440000|duration=1800|duration_time=0.020000|size=761|pos=421308|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d9fa6569 -packet|codec_type=audio|stream_index=0|pts=761400|pts_time=8.460000|dts=761400|dts_time=8.460000|duration=1800|duration_time=0.020000|size=828|pos=422248|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=761400|pts_time=8.460000|dts=761400|dts_time=8.460000|duration=1800|duration_time=0.020000|size=828|pos=422248|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:871a83c7 -packet|codec_type=audio|stream_index=0|pts=763200|pts_time=8.480000|dts=763200|dts_time=8.480000|duration=1800|duration_time=0.020000|size=759|pos=423188|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=763200|pts_time=8.480000|dts=763200|dts_time=8.480000|duration=1800|duration_time=0.020000|size=759|pos=423188|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ad2423ee -packet|codec_type=audio|stream_index=0|pts=765000|pts_time=8.500000|dts=765000|dts_time=8.500000|duration=1800|duration_time=0.020000|size=761|pos=424128|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=765000|pts_time=8.500000|dts=765000|dts_time=8.500000|duration=1800|duration_time=0.020000|size=761|pos=424128|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4e9b7b6e -packet|codec_type=audio|stream_index=0|pts=766800|pts_time=8.520000|dts=766800|dts_time=8.520000|duration=1800|duration_time=0.020000|size=762|pos=425068|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=766800|pts_time=8.520000|dts=766800|dts_time=8.520000|duration=1800|duration_time=0.020000|size=762|pos=425068|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:4aa3582f -packet|codec_type=audio|stream_index=0|pts=768600|pts_time=8.540000|dts=768600|dts_time=8.540000|duration=1800|duration_time=0.020000|size=761|pos=426008|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=768600|pts_time=8.540000|dts=768600|dts_time=8.540000|duration=1800|duration_time=0.020000|size=761|pos=426008|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:15952f9f -packet|codec_type=audio|stream_index=0|pts=770400|pts_time=8.560000|dts=770400|dts_time=8.560000|duration=1800|duration_time=0.020000|size=757|pos=426948|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=770400|pts_time=8.560000|dts=770400|dts_time=8.560000|duration=1800|duration_time=0.020000|size=757|pos=426948|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:55db10c7 -packet|codec_type=audio|stream_index=0|pts=772200|pts_time=8.580000|dts=772200|dts_time=8.580000|duration=1800|duration_time=0.020000|size=759|pos=427888|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=772200|pts_time=8.580000|dts=772200|dts_time=8.580000|duration=1800|duration_time=0.020000|size=759|pos=427888|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1cfff77c -packet|codec_type=audio|stream_index=0|pts=774000|pts_time=8.600000|dts=774000|dts_time=8.600000|duration=1800|duration_time=0.020000|size=759|pos=429204|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=774000|pts_time=8.600000|dts=774000|dts_time=8.600000|duration=1800|duration_time=0.020000|size=759|pos=429204|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:93bf7a2e -packet|codec_type=audio|stream_index=0|pts=775800|pts_time=8.620000|dts=775800|dts_time=8.620000|duration=1800|duration_time=0.020000|size=761|pos=430144|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=775800|pts_time=8.620000|dts=775800|dts_time=8.620000|duration=1800|duration_time=0.020000|size=761|pos=430144|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75577b1c -packet|codec_type=audio|stream_index=0|pts=777600|pts_time=8.640000|dts=777600|dts_time=8.640000|duration=1800|duration_time=0.020000|size=756|pos=431084|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=777600|pts_time=8.640000|dts=777600|dts_time=8.640000|duration=1800|duration_time=0.020000|size=756|pos=431084|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fe81112c -packet|codec_type=audio|stream_index=0|pts=779400|pts_time=8.660000|dts=779400|dts_time=8.660000|duration=1800|duration_time=0.020000|size=765|pos=432024|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=779400|pts_time=8.660000|dts=779400|dts_time=8.660000|duration=1800|duration_time=0.020000|size=765|pos=432024|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0ddc28c1 -packet|codec_type=audio|stream_index=0|pts=781200|pts_time=8.680000|dts=781200|dts_time=8.680000|duration=1800|duration_time=0.020000|size=759|pos=432964|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=781200|pts_time=8.680000|dts=781200|dts_time=8.680000|duration=1800|duration_time=0.020000|size=759|pos=432964|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9dda185 -packet|codec_type=audio|stream_index=0|pts=783000|pts_time=8.700000|dts=783000|dts_time=8.700000|duration=1800|duration_time=0.020000|size=759|pos=433904|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=783000|pts_time=8.700000|dts=783000|dts_time=8.700000|duration=1800|duration_time=0.020000|size=759|pos=433904|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e10197bd -packet|codec_type=audio|stream_index=0|pts=784800|pts_time=8.720000|dts=784800|dts_time=8.720000|duration=1800|duration_time=0.020000|size=761|pos=434844|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=784800|pts_time=8.720000|dts=784800|dts_time=8.720000|duration=1800|duration_time=0.020000|size=761|pos=434844|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f1683c68 -packet|codec_type=audio|stream_index=0|pts=786600|pts_time=8.740000|dts=786600|dts_time=8.740000|duration=1800|duration_time=0.020000|size=762|pos=435784|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=786600|pts_time=8.740000|dts=786600|dts_time=8.740000|duration=1800|duration_time=0.020000|size=762|pos=435784|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6eee942 -packet|codec_type=audio|stream_index=0|pts=788400|pts_time=8.760000|dts=788400|dts_time=8.760000|duration=1800|duration_time=0.020000|size=771|pos=436724|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=788400|pts_time=8.760000|dts=788400|dts_time=8.760000|duration=1800|duration_time=0.020000|size=771|pos=436724|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6ab1ef22 -packet|codec_type=audio|stream_index=0|pts=790200|pts_time=8.780000|dts=790200|dts_time=8.780000|duration=1800|duration_time=0.020000|size=758|pos=437664|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=790200|pts_time=8.780000|dts=790200|dts_time=8.780000|duration=1800|duration_time=0.020000|size=758|pos=437664|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6920a9e6 -packet|codec_type=audio|stream_index=0|pts=792000|pts_time=8.800000|dts=792000|dts_time=8.800000|duration=1800|duration_time=0.020000|size=759|pos=438980|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=792000|pts_time=8.800000|dts=792000|dts_time=8.800000|duration=1800|duration_time=0.020000|size=759|pos=438980|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b3ba03c7 -packet|codec_type=audio|stream_index=0|pts=793800|pts_time=8.820000|dts=793800|dts_time=8.820000|duration=1800|duration_time=0.020000|size=760|pos=439920|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=793800|pts_time=8.820000|dts=793800|dts_time=8.820000|duration=1800|duration_time=0.020000|size=760|pos=439920|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59f04151 -packet|codec_type=audio|stream_index=0|pts=795600|pts_time=8.840000|dts=795600|dts_time=8.840000|duration=1800|duration_time=0.020000|size=762|pos=440860|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=795600|pts_time=8.840000|dts=795600|dts_time=8.840000|duration=1800|duration_time=0.020000|size=762|pos=440860|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a9300525 -packet|codec_type=audio|stream_index=0|pts=797400|pts_time=8.860000|dts=797400|dts_time=8.860000|duration=1800|duration_time=0.020000|size=760|pos=441800|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=797400|pts_time=8.860000|dts=797400|dts_time=8.860000|duration=1800|duration_time=0.020000|size=760|pos=441800|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:06b28e48 -packet|codec_type=audio|stream_index=0|pts=799200|pts_time=8.880000|dts=799200|dts_time=8.880000|duration=1800|duration_time=0.020000|size=760|pos=442740|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=799200|pts_time=8.880000|dts=799200|dts_time=8.880000|duration=1800|duration_time=0.020000|size=760|pos=442740|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:99640c9a -packet|codec_type=audio|stream_index=0|pts=801000|pts_time=8.900000|dts=801000|dts_time=8.900000|duration=1800|duration_time=0.020000|size=757|pos=443680|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=801000|pts_time=8.900000|dts=801000|dts_time=8.900000|duration=1800|duration_time=0.020000|size=757|pos=443680|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:264f20e3 -packet|codec_type=audio|stream_index=0|pts=802800|pts_time=8.920000|dts=802800|dts_time=8.920000|duration=1800|duration_time=0.020000|size=762|pos=444620|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=802800|pts_time=8.920000|dts=802800|dts_time=8.920000|duration=1800|duration_time=0.020000|size=762|pos=444620|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:87799aaa -packet|codec_type=audio|stream_index=0|pts=804600|pts_time=8.940000|dts=804600|dts_time=8.940000|duration=1800|duration_time=0.020000|size=763|pos=445560|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=804600|pts_time=8.940000|dts=804600|dts_time=8.940000|duration=1800|duration_time=0.020000|size=763|pos=445560|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b2487f0b -packet|codec_type=audio|stream_index=0|pts=806400|pts_time=8.960000|dts=806400|dts_time=8.960000|duration=1800|duration_time=0.020000|size=835|pos=446500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=806400|pts_time=8.960000|dts=806400|dts_time=8.960000|duration=1800|duration_time=0.020000|size=835|pos=446500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5ff97478 -packet|codec_type=audio|stream_index=0|pts=808200|pts_time=8.980000|dts=808200|dts_time=8.980000|duration=1800|duration_time=0.020000|size=758|pos=447440|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=808200|pts_time=8.980000|dts=808200|dts_time=8.980000|duration=1800|duration_time=0.020000|size=758|pos=447440|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ee962000 -packet|codec_type=audio|stream_index=0|pts=810000|pts_time=9.000000|dts=810000|dts_time=9.000000|duration=1800|duration_time=0.020000|size=761|pos=448756|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=810000|pts_time=9.000000|dts=810000|dts_time=9.000000|duration=1800|duration_time=0.020000|size=761|pos=448756|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65a93707 -packet|codec_type=audio|stream_index=0|pts=811800|pts_time=9.020000|dts=811800|dts_time=9.020000|duration=1800|duration_time=0.020000|size=888|pos=449696|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=811800|pts_time=9.020000|dts=811800|dts_time=9.020000|duration=1800|duration_time=0.020000|size=888|pos=449696|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f365394f -packet|codec_type=audio|stream_index=0|pts=813600|pts_time=9.040000|dts=813600|dts_time=9.040000|duration=1800|duration_time=0.020000|size=758|pos=450636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=813600|pts_time=9.040000|dts=813600|dts_time=9.040000|duration=1800|duration_time=0.020000|size=758|pos=450636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:cc4aa3e5 -packet|codec_type=audio|stream_index=0|pts=815400|pts_time=9.060000|dts=815400|dts_time=9.060000|duration=1800|duration_time=0.020000|size=765|pos=451576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=815400|pts_time=9.060000|dts=815400|dts_time=9.060000|duration=1800|duration_time=0.020000|size=765|pos=451576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1fd5bac -packet|codec_type=audio|stream_index=0|pts=817200|pts_time=9.080000|dts=817200|dts_time=9.080000|duration=1800|duration_time=0.020000|size=761|pos=452516|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=817200|pts_time=9.080000|dts=817200|dts_time=9.080000|duration=1800|duration_time=0.020000|size=761|pos=452516|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:1590afda -packet|codec_type=audio|stream_index=0|pts=819000|pts_time=9.100000|dts=819000|dts_time=9.100000|duration=1800|duration_time=0.020000|size=764|pos=453456|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=819000|pts_time=9.100000|dts=819000|dts_time=9.100000|duration=1800|duration_time=0.020000|size=764|pos=453456|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e34e250 -packet|codec_type=audio|stream_index=0|pts=820800|pts_time=9.120000|dts=820800|dts_time=9.120000|duration=1800|duration_time=0.020000|size=762|pos=454396|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=820800|pts_time=9.120000|dts=820800|dts_time=9.120000|duration=1800|duration_time=0.020000|size=762|pos=454396|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:927657b5 -packet|codec_type=audio|stream_index=0|pts=822600|pts_time=9.140000|dts=822600|dts_time=9.140000|duration=1800|duration_time=0.020000|size=767|pos=455336|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=822600|pts_time=9.140000|dts=822600|dts_time=9.140000|duration=1800|duration_time=0.020000|size=767|pos=455336|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5261b6ab -packet|codec_type=audio|stream_index=0|pts=824400|pts_time=9.160000|dts=824400|dts_time=9.160000|duration=1800|duration_time=0.020000|size=759|pos=456276|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=824400|pts_time=9.160000|dts=824400|dts_time=9.160000|duration=1800|duration_time=0.020000|size=759|pos=456276|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:645fd792 -packet|codec_type=audio|stream_index=0|pts=826200|pts_time=9.180000|dts=826200|dts_time=9.180000|duration=1800|duration_time=0.020000|size=761|pos=457216|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=826200|pts_time=9.180000|dts=826200|dts_time=9.180000|duration=1800|duration_time=0.020000|size=761|pos=457216|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:240a9cd8 -packet|codec_type=audio|stream_index=0|pts=828000|pts_time=9.200000|dts=828000|dts_time=9.200000|duration=1800|duration_time=0.020000|size=762|pos=458532|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=828000|pts_time=9.200000|dts=828000|dts_time=9.200000|duration=1800|duration_time=0.020000|size=762|pos=458532|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:409c4ee6 -packet|codec_type=audio|stream_index=0|pts=829800|pts_time=9.220000|dts=829800|dts_time=9.220000|duration=1800|duration_time=0.020000|size=763|pos=459472|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=829800|pts_time=9.220000|dts=829800|dts_time=9.220000|duration=1800|duration_time=0.020000|size=763|pos=459472|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:a1e4f6c8 -packet|codec_type=audio|stream_index=0|pts=831600|pts_time=9.240000|dts=831600|dts_time=9.240000|duration=1800|duration_time=0.020000|size=760|pos=460412|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=831600|pts_time=9.240000|dts=831600|dts_time=9.240000|duration=1800|duration_time=0.020000|size=760|pos=460412|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e405b6d8 -packet|codec_type=audio|stream_index=0|pts=833400|pts_time=9.260000|dts=833400|dts_time=9.260000|duration=1800|duration_time=0.020000|size=832|pos=461352|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=833400|pts_time=9.260000|dts=833400|dts_time=9.260000|duration=1800|duration_time=0.020000|size=832|pos=461352|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:28926870 -packet|codec_type=audio|stream_index=0|pts=835200|pts_time=9.280000|dts=835200|dts_time=9.280000|duration=1800|duration_time=0.020000|size=761|pos=462292|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=835200|pts_time=9.280000|dts=835200|dts_time=9.280000|duration=1800|duration_time=0.020000|size=761|pos=462292|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:991eafa7 -packet|codec_type=audio|stream_index=0|pts=837000|pts_time=9.300000|dts=837000|dts_time=9.300000|duration=1800|duration_time=0.020000|size=887|pos=463232|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=837000|pts_time=9.300000|dts=837000|dts_time=9.300000|duration=1800|duration_time=0.020000|size=887|pos=463232|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2f2180e4 -packet|codec_type=audio|stream_index=0|pts=838800|pts_time=9.320000|dts=838800|dts_time=9.320000|duration=1800|duration_time=0.020000|size=765|pos=464172|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=838800|pts_time=9.320000|dts=838800|dts_time=9.320000|duration=1800|duration_time=0.020000|size=765|pos=464172|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c3b931ab -packet|codec_type=audio|stream_index=0|pts=840600|pts_time=9.340000|dts=840600|dts_time=9.340000|duration=1800|duration_time=0.020000|size=763|pos=465112|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=840600|pts_time=9.340000|dts=840600|dts_time=9.340000|duration=1800|duration_time=0.020000|size=763|pos=465112|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09c95d1c -packet|codec_type=audio|stream_index=0|pts=842400|pts_time=9.360000|dts=842400|dts_time=9.360000|duration=1800|duration_time=0.020000|size=763|pos=466052|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=842400|pts_time=9.360000|dts=842400|dts_time=9.360000|duration=1800|duration_time=0.020000|size=763|pos=466052|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5a90f4d9 -packet|codec_type=audio|stream_index=0|pts=844200|pts_time=9.380000|dts=844200|dts_time=9.380000|duration=1800|duration_time=0.020000|size=952|pos=466992|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=844200|pts_time=9.380000|dts=844200|dts_time=9.380000|duration=1800|duration_time=0.020000|size=952|pos=466992|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2e1338bd -packet|codec_type=audio|stream_index=0|pts=846000|pts_time=9.400000|dts=846000|dts_time=9.400000|duration=1800|duration_time=0.020000|size=953|pos=468496|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=846000|pts_time=9.400000|dts=846000|dts_time=9.400000|duration=1800|duration_time=0.020000|size=953|pos=468496|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:db87e979 -packet|codec_type=audio|stream_index=0|pts=847800|pts_time=9.420000|dts=847800|dts_time=9.420000|duration=1800|duration_time=0.020000|size=945|pos=469624|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=847800|pts_time=9.420000|dts=847800|dts_time=9.420000|duration=1800|duration_time=0.020000|size=945|pos=469624|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d55815d6 -packet|codec_type=audio|stream_index=0|pts=849600|pts_time=9.440000|dts=849600|dts_time=9.440000|duration=1800|duration_time=0.020000|size=948|pos=470752|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=849600|pts_time=9.440000|dts=849600|dts_time=9.440000|duration=1800|duration_time=0.020000|size=948|pos=470752|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e31e5728 -packet|codec_type=audio|stream_index=0|pts=851400|pts_time=9.460000|dts=851400|dts_time=9.460000|duration=1800|duration_time=0.020000|size=951|pos=471880|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=851400|pts_time=9.460000|dts=851400|dts_time=9.460000|duration=1800|duration_time=0.020000|size=951|pos=471880|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:49e86c3d -packet|codec_type=audio|stream_index=0|pts=853200|pts_time=9.480000|dts=853200|dts_time=9.480000|duration=1800|duration_time=0.020000|size=826|pos=473008|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=853200|pts_time=9.480000|dts=853200|dts_time=9.480000|duration=1800|duration_time=0.020000|size=826|pos=473008|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:13cefb19 -packet|codec_type=audio|stream_index=0|pts=855000|pts_time=9.500000|dts=855000|dts_time=9.500000|duration=1800|duration_time=0.020000|size=763|pos=473948|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=855000|pts_time=9.500000|dts=855000|dts_time=9.500000|duration=1800|duration_time=0.020000|size=763|pos=473948|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8d9b7d72 -packet|codec_type=audio|stream_index=0|pts=856800|pts_time=9.520000|dts=856800|dts_time=9.520000|duration=1800|duration_time=0.020000|size=763|pos=474888|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=856800|pts_time=9.520000|dts=856800|dts_time=9.520000|duration=1800|duration_time=0.020000|size=763|pos=474888|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:d55b35fb -packet|codec_type=audio|stream_index=0|pts=858600|pts_time=9.540000|dts=858600|dts_time=9.540000|duration=1800|duration_time=0.020000|size=766|pos=475828|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=858600|pts_time=9.540000|dts=858600|dts_time=9.540000|duration=1800|duration_time=0.020000|size=766|pos=475828|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3e10c46a -packet|codec_type=audio|stream_index=0|pts=860400|pts_time=9.560000|dts=860400|dts_time=9.560000|duration=1800|duration_time=0.020000|size=946|pos=476768|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=860400|pts_time=9.560000|dts=860400|dts_time=9.560000|duration=1800|duration_time=0.020000|size=946|pos=476768|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:924e67eb -packet|codec_type=audio|stream_index=0|pts=862200|pts_time=9.580000|dts=862200|dts_time=9.580000|duration=1800|duration_time=0.020000|size=762|pos=477896|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=862200|pts_time=9.580000|dts=862200|dts_time=9.580000|duration=1800|duration_time=0.020000|size=762|pos=477896|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:008c6ebb -packet|codec_type=audio|stream_index=0|pts=864000|pts_time=9.600000|dts=864000|dts_time=9.600000|duration=1800|duration_time=0.020000|size=765|pos=479212|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=864000|pts_time=9.600000|dts=864000|dts_time=9.600000|duration=1800|duration_time=0.020000|size=765|pos=479212|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:96d72d3f -packet|codec_type=audio|stream_index=0|pts=865800|pts_time=9.620000|dts=865800|dts_time=9.620000|duration=1800|duration_time=0.020000|size=763|pos=480152|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=865800|pts_time=9.620000|dts=865800|dts_time=9.620000|duration=1800|duration_time=0.020000|size=763|pos=480152|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6f40bb5a -packet|codec_type=audio|stream_index=0|pts=867600|pts_time=9.640000|dts=867600|dts_time=9.640000|duration=1800|duration_time=0.020000|size=761|pos=481092|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=867600|pts_time=9.640000|dts=867600|dts_time=9.640000|duration=1800|duration_time=0.020000|size=761|pos=481092|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:f6ba1f01 -packet|codec_type=audio|stream_index=0|pts=869400|pts_time=9.660000|dts=869400|dts_time=9.660000|duration=1800|duration_time=0.020000|size=760|pos=482032|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=869400|pts_time=9.660000|dts=869400|dts_time=9.660000|duration=1800|duration_time=0.020000|size=760|pos=482032|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b610a31e -packet|codec_type=audio|stream_index=0|pts=871200|pts_time=9.680000|dts=871200|dts_time=9.680000|duration=1800|duration_time=0.020000|size=757|pos=482972|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=871200|pts_time=9.680000|dts=871200|dts_time=9.680000|duration=1800|duration_time=0.020000|size=757|pos=482972|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:64dde46b -packet|codec_type=audio|stream_index=0|pts=873000|pts_time=9.700000|dts=873000|dts_time=9.700000|duration=1800|duration_time=0.020000|size=757|pos=483912|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=873000|pts_time=9.700000|dts=873000|dts_time=9.700000|duration=1800|duration_time=0.020000|size=757|pos=483912|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:8f794e6c -packet|codec_type=audio|stream_index=0|pts=874800|pts_time=9.720000|dts=874800|dts_time=9.720000|duration=1800|duration_time=0.020000|size=762|pos=484852|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=874800|pts_time=9.720000|dts=874800|dts_time=9.720000|duration=1800|duration_time=0.020000|size=762|pos=484852|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:65c6284c -packet|codec_type=audio|stream_index=0|pts=876600|pts_time=9.740000|dts=876600|dts_time=9.740000|duration=1800|duration_time=0.020000|size=760|pos=485792|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=876600|pts_time=9.740000|dts=876600|dts_time=9.740000|duration=1800|duration_time=0.020000|size=760|pos=485792|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7dead06c -packet|codec_type=audio|stream_index=0|pts=878400|pts_time=9.760000|dts=878400|dts_time=9.760000|duration=1800|duration_time=0.020000|size=763|pos=486732|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=878400|pts_time=9.760000|dts=878400|dts_time=9.760000|duration=1800|duration_time=0.020000|size=763|pos=486732|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b0e145b1 -packet|codec_type=audio|stream_index=0|pts=880200|pts_time=9.780000|dts=880200|dts_time=9.780000|duration=1800|duration_time=0.020000|size=764|pos=487672|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=880200|pts_time=9.780000|dts=880200|dts_time=9.780000|duration=1800|duration_time=0.020000|size=764|pos=487672|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:3d2553f6 -packet|codec_type=audio|stream_index=0|pts=882000|pts_time=9.800000|dts=882000|dts_time=9.800000|duration=1800|duration_time=0.020000|size=946|pos=488988|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=882000|pts_time=9.800000|dts=882000|dts_time=9.800000|duration=1800|duration_time=0.020000|size=946|pos=488988|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e808f1d2 -packet|codec_type=audio|stream_index=0|pts=883800|pts_time=9.820000|dts=883800|dts_time=9.820000|duration=1800|duration_time=0.020000|size=946|pos=490116|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=883800|pts_time=9.820000|dts=883800|dts_time=9.820000|duration=1800|duration_time=0.020000|size=946|pos=490116|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6b408528 -packet|codec_type=audio|stream_index=0|pts=885600|pts_time=9.840000|dts=885600|dts_time=9.840000|duration=1800|duration_time=0.020000|size=949|pos=491244|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=885600|pts_time=9.840000|dts=885600|dts_time=9.840000|duration=1800|duration_time=0.020000|size=949|pos=491244|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e51d96e4 -packet|codec_type=audio|stream_index=0|pts=887400|pts_time=9.860000|dts=887400|dts_time=9.860000|duration=1800|duration_time=0.020000|size=946|pos=492372|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=887400|pts_time=9.860000|dts=887400|dts_time=9.860000|duration=1800|duration_time=0.020000|size=946|pos=492372|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:c2df3280 -packet|codec_type=audio|stream_index=0|pts=889200|pts_time=9.880000|dts=889200|dts_time=9.880000|duration=1800|duration_time=0.020000|size=940|pos=493500|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=889200|pts_time=9.880000|dts=889200|dts_time=9.880000|duration=1800|duration_time=0.020000|size=940|pos=493500|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7bb5a137 -packet|codec_type=audio|stream_index=0|pts=891000|pts_time=9.900000|dts=891000|dts_time=9.900000|duration=1800|duration_time=0.020000|size=762|pos=494628|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=891000|pts_time=9.900000|dts=891000|dts_time=9.900000|duration=1800|duration_time=0.020000|size=762|pos=494628|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:12fcc651 -packet|codec_type=audio|stream_index=0|pts=892800|pts_time=9.920000|dts=892800|dts_time=9.920000|duration=1800|duration_time=0.020000|size=759|pos=495568|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=892800|pts_time=9.920000|dts=892800|dts_time=9.920000|duration=1800|duration_time=0.020000|size=759|pos=495568|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:b402a4c8 -packet|codec_type=audio|stream_index=0|pts=894600|pts_time=9.940000|dts=894600|dts_time=9.940000|duration=1800|duration_time=0.020000|size=942|pos=496508|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=894600|pts_time=9.940000|dts=894600|dts_time=9.940000|duration=1800|duration_time=0.020000|size=942|pos=496508|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:bfe52a16 -packet|codec_type=audio|stream_index=0|pts=896400|pts_time=9.960000|dts=896400|dts_time=9.960000|duration=1800|duration_time=0.020000|size=764|pos=497636|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=896400|pts_time=9.960000|dts=896400|dts_time=9.960000|duration=1800|duration_time=0.020000|size=764|pos=497636|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:09372283 -packet|codec_type=audio|stream_index=0|pts=898200|pts_time=9.980000|dts=898200|dts_time=9.980000|duration=1800|duration_time=0.020000|size=759|pos=498576|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=898200|pts_time=9.980000|dts=898200|dts_time=9.980000|duration=1800|duration_time=0.020000|size=759|pos=498576|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5a27db5c -packet|codec_type=audio|stream_index=0|pts=900000|pts_time=10.000000|dts=900000|dts_time=10.000000|duration=1800|duration_time=0.020000|size=760|pos=499892|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=900000|pts_time=10.000000|dts=900000|dts_time=10.000000|duration=1800|duration_time=0.020000|size=760|pos=499892|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:0821b0cd -packet|codec_type=audio|stream_index=0|pts=901800|pts_time=10.020000|dts=901800|dts_time=10.020000|duration=1800|duration_time=0.020000|size=757|pos=500832|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=901800|pts_time=10.020000|dts=901800|dts_time=10.020000|duration=1800|duration_time=0.020000|size=757|pos=500832|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:91af6b99 -packet|codec_type=audio|stream_index=0|pts=903600|pts_time=10.040000|dts=903600|dts_time=10.040000|duration=1800|duration_time=0.020000|size=941|pos=501772|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=903600|pts_time=10.040000|dts=903600|dts_time=10.040000|duration=1800|duration_time=0.020000|size=941|pos=501772|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:5296a88a -packet|codec_type=audio|stream_index=0|pts=905400|pts_time=10.060000|dts=905400|dts_time=10.060000|duration=1800|duration_time=0.020000|size=943|pos=502900|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=905400|pts_time=10.060000|dts=905400|dts_time=10.060000|duration=1800|duration_time=0.020000|size=943|pos=502900|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:e75e69d4 -packet|codec_type=audio|stream_index=0|pts=907200|pts_time=10.080000|dts=907200|dts_time=10.080000|duration=1800|duration_time=0.020000|size=759|pos=504028|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=907200|pts_time=10.080000|dts=907200|dts_time=10.080000|duration=1800|duration_time=0.020000|size=759|pos=504028|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:6a5b92cd -packet|codec_type=audio|stream_index=0|pts=909000|pts_time=10.100000|dts=909000|dts_time=10.100000|duration=1800|duration_time=0.020000|size=759|pos=504968|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=909000|pts_time=10.100000|dts=909000|dts_time=10.100000|duration=1800|duration_time=0.020000|size=759|pos=504968|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:ec30c088 -packet|codec_type=audio|stream_index=0|pts=910800|pts_time=10.120000|dts=910800|dts_time=10.120000|duration=1800|duration_time=0.020000|size=762|pos=505908|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=910800|pts_time=10.120000|dts=910800|dts_time=10.120000|duration=1800|duration_time=0.020000|size=762|pos=505908|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:2c73f2ff -packet|codec_type=audio|stream_index=0|pts=912600|pts_time=10.140000|dts=912600|dts_time=10.140000|duration=1800|duration_time=0.020000|size=831|pos=506848|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=912600|pts_time=10.140000|dts=912600|dts_time=10.140000|duration=1800|duration_time=0.020000|size=831|pos=506848|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:7f7cb041 -packet|codec_type=audio|stream_index=0|pts=914400|pts_time=10.160000|dts=914400|dts_time=10.160000|duration=1800|duration_time=0.020000|size=756|pos=507788|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=914400|pts_time=10.160000|dts=914400|dts_time=10.160000|duration=1800|duration_time=0.020000|size=756|pos=507788|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:52ef1db9 -packet|codec_type=audio|stream_index=0|pts=916200|pts_time=10.180000|dts=916200|dts_time=10.180000|duration=1800|duration_time=0.020000|size=760|pos=508728|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=916200|pts_time=10.180000|dts=916200|dts_time=10.180000|duration=1800|duration_time=0.020000|size=760|pos=508728|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:fdf0ce4a -packet|codec_type=audio|stream_index=0|pts=918000|pts_time=10.200000|dts=918000|dts_time=10.200000|duration=1800|duration_time=0.020000|size=761|pos=510044|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=918000|pts_time=10.200000|dts=918000|dts_time=10.200000|duration=1800|duration_time=0.020000|size=761|pos=510044|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:75113c11 -packet|codec_type=audio|stream_index=0|pts=919800|pts_time=10.220000|dts=919800|dts_time=10.220000|duration=1800|duration_time=0.020000|size=759|pos=510984|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=189 +packet|codec_type=audio|stream_index=0|pts=919800|pts_time=10.220000|dts=919800|dts_time=10.220000|duration=1800|duration_time=0.020000|size=759|pos=510984|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=189 |data_hash=CRC32:59fc266f -stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=Opus|codec_tag=0x7375704f|sample_fmt=fltp|sample_rate=48000|channels=8|channel_layout=7.1|bits_per_sample=0|id=0x44|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=919800|duration=10.220000|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=512|extradata_hash=CRC32:6d6089a7|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=opus|profile=unknown|codec_type=audio|codec_tag_string=Opus|codec_tag=0x7375704f|sample_fmt=fltp|sample_rate=48000|channels=8|channel_layout=7.1|bits_per_sample=0|id=0x44|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=919800|duration=10.220000|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=512|extradata_size=29|extradata_hash=CRC32:6d6089a7|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=test-8-7.1.opus-small.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=0.000000|duration=10.220000|size=512000|bit_rate=400782|probe_score=50 diff --git a/tests/ref/fate/ts-small-demux b/tests/ref/fate/ts-small-demux index 264d878d5b..3452fad4be 100644 --- a/tests/ref/fate/ts-small-demux +++ b/tests/ref/fate/ts-small-demux @@ -1,149 +1,149 @@ -packet|codec_type=video|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=6000|duration_time=0.066667|size=1290|pos=564|flags=K_side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=126000|pts_time=1.400000|dts=126000|dts_time=1.400000|duration=6000|duration_time=0.066667|size=1290|pos=564|flags=K_|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:9c4b744e -packet|codec_type=video|stream_index=0|pts=132000|pts_time=1.466667|dts=132000|dts_time=1.466667|duration=6000|duration_time=0.066667|size=21|pos=2068|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=132000|pts_time=1.466667|dts=132000|dts_time=1.466667|duration=6000|duration_time=0.066667|size=21|pos=2068|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f5490de8 -packet|codec_type=video|stream_index=0|pts=138000|pts_time=1.533333|dts=138000|dts_time=1.533333|duration=6000|duration_time=0.066667|size=15|pos=2256|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=138000|pts_time=1.533333|dts=138000|dts_time=1.533333|duration=6000|duration_time=0.066667|size=15|pos=2256|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=6000|duration_time=0.066667|size=15|pos=2444|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=144000|pts_time=1.600000|dts=144000|dts_time=1.600000|duration=6000|duration_time=0.066667|size=15|pos=2444|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=150000|pts_time=1.666667|dts=150000|dts_time=1.666667|duration=6000|duration_time=0.066667|size=15|pos=2632|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=150000|pts_time=1.666667|dts=150000|dts_time=1.666667|duration=6000|duration_time=0.066667|size=15|pos=2632|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=156000|pts_time=1.733333|dts=156000|dts_time=1.733333|duration=6000|duration_time=0.066667|size=15|pos=2820|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=156000|pts_time=1.733333|dts=156000|dts_time=1.733333|duration=6000|duration_time=0.066667|size=15|pos=2820|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=6000|duration_time=0.066667|size=15|pos=3008|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=162000|pts_time=1.800000|dts=162000|dts_time=1.800000|duration=6000|duration_time=0.066667|size=15|pos=3008|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=168000|pts_time=1.866667|dts=168000|dts_time=1.866667|duration=6000|duration_time=0.066667|size=15|pos=3196|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=168000|pts_time=1.866667|dts=168000|dts_time=1.866667|duration=6000|duration_time=0.066667|size=15|pos=3196|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=174000|pts_time=1.933333|dts=174000|dts_time=1.933333|duration=6000|duration_time=0.066667|size=15|pos=3384|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=174000|pts_time=1.933333|dts=174000|dts_time=1.933333|duration=6000|duration_time=0.066667|size=15|pos=3384|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=6000|duration_time=0.066667|size=15|pos=3572|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=180000|pts_time=2.000000|dts=180000|dts_time=2.000000|duration=6000|duration_time=0.066667|size=15|pos=3572|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=186000|pts_time=2.066667|dts=186000|dts_time=2.066667|duration=6000|duration_time=0.066667|size=15|pos=3760|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=186000|pts_time=2.066667|dts=186000|dts_time=2.066667|duration=6000|duration_time=0.066667|size=15|pos=3760|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=192000|pts_time=2.133333|dts=192000|dts_time=2.133333|duration=6000|duration_time=0.066667|size=15|pos=3948|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=192000|pts_time=2.133333|dts=192000|dts_time=2.133333|duration=6000|duration_time=0.066667|size=15|pos=3948|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=6000|duration_time=0.066667|size=15|pos=4136|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=198000|pts_time=2.200000|dts=198000|dts_time=2.200000|duration=6000|duration_time=0.066667|size=15|pos=4136|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=204000|pts_time=2.266667|dts=204000|dts_time=2.266667|duration=6000|duration_time=0.066667|size=15|pos=4324|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=204000|pts_time=2.266667|dts=204000|dts_time=2.266667|duration=6000|duration_time=0.066667|size=15|pos=4324|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=210000|pts_time=2.333333|dts=210000|dts_time=2.333333|duration=6000|duration_time=0.066667|size=15|pos=4512|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=210000|pts_time=2.333333|dts=210000|dts_time=2.333333|duration=6000|duration_time=0.066667|size=15|pos=4512|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=6000|duration_time=0.066667|size=15|pos=4700|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=216000|pts_time=2.400000|dts=216000|dts_time=2.400000|duration=6000|duration_time=0.066667|size=15|pos=4700|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=222000|pts_time=2.466667|dts=222000|dts_time=2.466667|duration=6000|duration_time=0.066667|size=15|pos=4888|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=222000|pts_time=2.466667|dts=222000|dts_time=2.466667|duration=6000|duration_time=0.066667|size=15|pos=4888|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=228000|pts_time=2.533333|dts=228000|dts_time=2.533333|duration=6000|duration_time=0.066667|size=15|pos=5076|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=228000|pts_time=2.533333|dts=228000|dts_time=2.533333|duration=6000|duration_time=0.066667|size=15|pos=5076|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=6000|duration_time=0.066667|size=15|pos=5264|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=234000|pts_time=2.600000|dts=234000|dts_time=2.600000|duration=6000|duration_time=0.066667|size=15|pos=5264|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=240000|pts_time=2.666667|dts=240000|dts_time=2.666667|duration=6000|duration_time=0.066667|size=15|pos=5452|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=240000|pts_time=2.666667|dts=240000|dts_time=2.666667|duration=6000|duration_time=0.066667|size=15|pos=5452|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=246000|pts_time=2.733333|dts=246000|dts_time=2.733333|duration=6000|duration_time=0.066667|size=15|pos=5640|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=246000|pts_time=2.733333|dts=246000|dts_time=2.733333|duration=6000|duration_time=0.066667|size=15|pos=5640|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=6000|duration_time=0.066667|size=15|pos=5828|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=252000|pts_time=2.800000|dts=252000|dts_time=2.800000|duration=6000|duration_time=0.066667|size=15|pos=5828|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=258000|pts_time=2.866667|dts=258000|dts_time=2.866667|duration=6000|duration_time=0.066667|size=15|pos=6016|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=258000|pts_time=2.866667|dts=258000|dts_time=2.866667|duration=6000|duration_time=0.066667|size=15|pos=6016|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=264000|pts_time=2.933333|dts=264000|dts_time=2.933333|duration=6000|duration_time=0.066667|size=15|pos=6204|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=264000|pts_time=2.933333|dts=264000|dts_time=2.933333|duration=6000|duration_time=0.066667|size=15|pos=6204|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=6000|duration_time=0.066667|size=15|pos=6392|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=270000|pts_time=3.000000|dts=270000|dts_time=3.000000|duration=6000|duration_time=0.066667|size=15|pos=6392|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=276000|pts_time=3.066667|dts=276000|dts_time=3.066667|duration=6000|duration_time=0.066667|size=15|pos=6580|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=276000|pts_time=3.066667|dts=276000|dts_time=3.066667|duration=6000|duration_time=0.066667|size=15|pos=6580|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=282000|pts_time=3.133333|dts=282000|dts_time=3.133333|duration=6000|duration_time=0.066667|size=15|pos=6768|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=282000|pts_time=3.133333|dts=282000|dts_time=3.133333|duration=6000|duration_time=0.066667|size=15|pos=6768|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=6000|duration_time=0.066667|size=15|pos=6956|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=288000|pts_time=3.200000|dts=288000|dts_time=3.200000|duration=6000|duration_time=0.066667|size=15|pos=6956|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=294000|pts_time=3.266667|dts=294000|dts_time=3.266667|duration=6000|duration_time=0.066667|size=15|pos=7144|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=294000|pts_time=3.266667|dts=294000|dts_time=3.266667|duration=6000|duration_time=0.066667|size=15|pos=7144|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=300000|pts_time=3.333333|dts=300000|dts_time=3.333333|duration=6000|duration_time=0.066667|size=15|pos=7332|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=300000|pts_time=3.333333|dts=300000|dts_time=3.333333|duration=6000|duration_time=0.066667|size=15|pos=7332|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=6000|duration_time=0.066667|size=15|pos=7520|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=306000|pts_time=3.400000|dts=306000|dts_time=3.400000|duration=6000|duration_time=0.066667|size=15|pos=7520|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=312000|pts_time=3.466667|dts=312000|dts_time=3.466667|duration=6000|duration_time=0.066667|size=15|pos=7708|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=312000|pts_time=3.466667|dts=312000|dts_time=3.466667|duration=6000|duration_time=0.066667|size=15|pos=7708|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=318000|pts_time=3.533333|dts=318000|dts_time=3.533333|duration=6000|duration_time=0.066667|size=15|pos=7896|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=318000|pts_time=3.533333|dts=318000|dts_time=3.533333|duration=6000|duration_time=0.066667|size=15|pos=7896|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=6000|duration_time=0.066667|size=15|pos=8460|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=324000|pts_time=3.600000|dts=324000|dts_time=3.600000|duration=6000|duration_time=0.066667|size=15|pos=8460|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=330000|pts_time=3.666667|dts=330000|dts_time=3.666667|duration=6000|duration_time=0.066667|size=15|pos=8648|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=330000|pts_time=3.666667|dts=330000|dts_time=3.666667|duration=6000|duration_time=0.066667|size=15|pos=8648|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=336000|pts_time=3.733333|dts=336000|dts_time=3.733333|duration=6000|duration_time=0.066667|size=15|pos=8836|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=336000|pts_time=3.733333|dts=336000|dts_time=3.733333|duration=6000|duration_time=0.066667|size=15|pos=8836|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=6000|duration_time=0.066667|size=15|pos=9024|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=342000|pts_time=3.800000|dts=342000|dts_time=3.800000|duration=6000|duration_time=0.066667|size=15|pos=9024|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=348000|pts_time=3.866667|dts=348000|dts_time=3.866667|duration=6000|duration_time=0.066667|size=15|pos=9212|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=348000|pts_time=3.866667|dts=348000|dts_time=3.866667|duration=6000|duration_time=0.066667|size=15|pos=9212|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=354000|pts_time=3.933333|dts=354000|dts_time=3.933333|duration=6000|duration_time=0.066667|size=15|pos=9400|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=354000|pts_time=3.933333|dts=354000|dts_time=3.933333|duration=6000|duration_time=0.066667|size=15|pos=9400|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=6000|duration_time=0.066667|size=15|pos=9588|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=360000|pts_time=4.000000|dts=360000|dts_time=4.000000|duration=6000|duration_time=0.066667|size=15|pos=9588|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=366000|pts_time=4.066667|dts=366000|dts_time=4.066667|duration=6000|duration_time=0.066667|size=15|pos=9776|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=366000|pts_time=4.066667|dts=366000|dts_time=4.066667|duration=6000|duration_time=0.066667|size=15|pos=9776|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=372000|pts_time=4.133333|dts=372000|dts_time=4.133333|duration=6000|duration_time=0.066667|size=15|pos=9964|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=372000|pts_time=4.133333|dts=372000|dts_time=4.133333|duration=6000|duration_time=0.066667|size=15|pos=9964|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=6000|duration_time=0.066667|size=15|pos=10152|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=378000|pts_time=4.200000|dts=378000|dts_time=4.200000|duration=6000|duration_time=0.066667|size=15|pos=10152|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=384000|pts_time=4.266667|dts=384000|dts_time=4.266667|duration=6000|duration_time=0.066667|size=15|pos=10340|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=384000|pts_time=4.266667|dts=384000|dts_time=4.266667|duration=6000|duration_time=0.066667|size=15|pos=10340|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=390000|pts_time=4.333333|dts=390000|dts_time=4.333333|duration=6000|duration_time=0.066667|size=15|pos=10528|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=390000|pts_time=4.333333|dts=390000|dts_time=4.333333|duration=6000|duration_time=0.066667|size=15|pos=10528|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=6000|duration_time=0.066667|size=15|pos=10716|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=396000|pts_time=4.400000|dts=396000|dts_time=4.400000|duration=6000|duration_time=0.066667|size=15|pos=10716|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=402000|pts_time=4.466667|dts=402000|dts_time=4.466667|duration=6000|duration_time=0.066667|size=15|pos=10904|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=402000|pts_time=4.466667|dts=402000|dts_time=4.466667|duration=6000|duration_time=0.066667|size=15|pos=10904|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=408000|pts_time=4.533333|dts=408000|dts_time=4.533333|duration=6000|duration_time=0.066667|size=15|pos=11092|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=408000|pts_time=4.533333|dts=408000|dts_time=4.533333|duration=6000|duration_time=0.066667|size=15|pos=11092|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=6000|duration_time=0.066667|size=15|pos=11280|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=414000|pts_time=4.600000|dts=414000|dts_time=4.600000|duration=6000|duration_time=0.066667|size=15|pos=11280|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=420000|pts_time=4.666667|dts=420000|dts_time=4.666667|duration=6000|duration_time=0.066667|size=15|pos=11468|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=420000|pts_time=4.666667|dts=420000|dts_time=4.666667|duration=6000|duration_time=0.066667|size=15|pos=11468|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=426000|pts_time=4.733333|dts=426000|dts_time=4.733333|duration=6000|duration_time=0.066667|size=15|pos=11656|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=426000|pts_time=4.733333|dts=426000|dts_time=4.733333|duration=6000|duration_time=0.066667|size=15|pos=11656|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=6000|duration_time=0.066667|size=15|pos=11844|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=432000|pts_time=4.800000|dts=432000|dts_time=4.800000|duration=6000|duration_time=0.066667|size=15|pos=11844|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=438000|pts_time=4.866667|dts=438000|dts_time=4.866667|duration=6000|duration_time=0.066667|size=15|pos=12032|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=438000|pts_time=4.866667|dts=438000|dts_time=4.866667|duration=6000|duration_time=0.066667|size=15|pos=12032|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=444000|pts_time=4.933333|dts=444000|dts_time=4.933333|duration=6000|duration_time=0.066667|size=15|pos=12220|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=444000|pts_time=4.933333|dts=444000|dts_time=4.933333|duration=6000|duration_time=0.066667|size=15|pos=12220|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=6000|duration_time=0.066667|size=15|pos=12408|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=450000|pts_time=5.000000|dts=450000|dts_time=5.000000|duration=6000|duration_time=0.066667|size=15|pos=12408|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=456000|pts_time=5.066667|dts=456000|dts_time=5.066667|duration=6000|duration_time=0.066667|size=15|pos=12596|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=456000|pts_time=5.066667|dts=456000|dts_time=5.066667|duration=6000|duration_time=0.066667|size=15|pos=12596|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:0157e1a0 -packet|codec_type=video|stream_index=0|pts=462000|pts_time=5.133333|dts=462000|dts_time=5.133333|duration=6000|duration_time=0.066667|size=15|pos=12784|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=462000|pts_time=5.133333|dts=462000|dts_time=5.133333|duration=6000|duration_time=0.066667|size=15|pos=12784|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:10095665 -packet|codec_type=video|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=6000|duration_time=0.066667|size=15|pos=12972|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=468000|pts_time=5.200000|dts=468000|dts_time=5.200000|duration=6000|duration_time=0.066667|size=15|pos=12972|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:28441085 -packet|codec_type=video|stream_index=0|pts=474000|pts_time=5.266667|dts=474000|dts_time=5.266667|duration=6000|duration_time=0.066667|size=15|pos=13160|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=474000|pts_time=5.266667|dts=474000|dts_time=5.266667|duration=6000|duration_time=0.066667|size=15|pos=13160|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:6093dba5 -packet|codec_type=video|stream_index=0|pts=480000|pts_time=5.333333|dts=480000|dts_time=5.333333|duration=6000|duration_time=0.066667|size=15|pos=13348|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=480000|pts_time=5.333333|dts=480000|dts_time=5.333333|duration=6000|duration_time=0.066667|size=15|pos=13348|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:58de9d45 -packet|codec_type=video|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=6000|duration_time=0.066667|size=15|pos=13536|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=486000|pts_time=5.400000|dts=486000|dts_time=5.400000|duration=6000|duration_time=0.066667|size=15|pos=13536|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:f13c4de5 -packet|codec_type=video|stream_index=0|pts=492000|pts_time=5.466667|dts=492000|dts_time=5.466667|duration=6000|duration_time=0.066667|size=15|pos=13724|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=492000|pts_time=5.466667|dts=492000|dts_time=5.466667|duration=6000|duration_time=0.066667|size=15|pos=13724|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:c9710b05 -packet|codec_type=video|stream_index=0|pts=498000|pts_time=5.533333|dts=498000|dts_time=5.533333|duration=6000|duration_time=0.066667|size=15|pos=13912|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=498000|pts_time=5.533333|dts=498000|dts_time=5.533333|duration=6000|duration_time=0.066667|size=15|pos=13912|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:81a6c025 -packet|codec_type=video|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=6000|duration_time=0.066667|size=15|pos=14100|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=504000|pts_time=5.600000|dts=504000|dts_time=5.600000|duration=6000|duration_time=0.066667|size=15|pos=14100|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:b9eb86c5 -packet|codec_type=video|stream_index=0|pts=510000|pts_time=5.666667|dts=510000|dts_time=5.666667|duration=6000|duration_time=0.066667|size=15|pos=14288|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=510000|pts_time=5.666667|dts=510000|dts_time=5.666667|duration=6000|duration_time=0.066667|size=15|pos=14288|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:a8b53100 -packet|codec_type=video|stream_index=0|pts=516000|pts_time=5.733333|dts=516000|dts_time=5.733333|duration=6000|duration_time=0.066667|size=15|pos=14476|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=516000|pts_time=5.733333|dts=516000|dts_time=5.733333|duration=6000|duration_time=0.066667|size=15|pos=14476|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:90f877e0 -packet|codec_type=video|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=6000|duration_time=0.066667|size=15|pos=14664|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=522000|pts_time=5.800000|dts=522000|dts_time=5.800000|duration=6000|duration_time=0.066667|size=15|pos=14664|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:d82fbcc0 -packet|codec_type=video|stream_index=0|pts=528000|pts_time=5.866667|dts=528000|dts_time=5.866667|duration=6000|duration_time=0.066667|size=15|pos=14852|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=528000|pts_time=5.866667|dts=528000|dts_time=5.866667|duration=6000|duration_time=0.066667|size=15|pos=14852|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:e062fa20 -packet|codec_type=video|stream_index=0|pts=534000|pts_time=5.933333|dts=534000|dts_time=5.933333|duration=6000|duration_time=0.066667|size=15|pos=15040|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=534000|pts_time=5.933333|dts=534000|dts_time=5.933333|duration=6000|duration_time=0.066667|size=15|pos=15040|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:49802a80 -packet|codec_type=video|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=6000|duration_time=0.066667|size=15|pos=15228|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=540000|pts_time=6.000000|dts=540000|dts_time=6.000000|duration=6000|duration_time=0.066667|size=15|pos=15228|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:71cd6c60 -packet|codec_type=video|stream_index=0|pts=546000|pts_time=6.066667|dts=546000|dts_time=6.066667|duration=6000|duration_time=0.066667|size=15|pos=15416|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=546000|pts_time=6.066667|dts=546000|dts_time=6.066667|duration=6000|duration_time=0.066667|size=15|pos=15416|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:391aa740 -packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|dts_time=6.133333|duration=6000|duration_time=0.066667|size=16|pos=15604|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=552000|pts_time=6.133333|dts=552000|dts_time=6.133333|duration=6000|duration_time=0.066667|size=16|pos=15604|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:cca62b67 -packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=__side_data|side_data_type=MPEGTS Stream ID|id=224 +packet|codec_type=video|stream_index=0|pts=558000|pts_time=6.200000|dts=558000|dts_time=6.200000|duration=6000|duration_time=0.066667|size=16|pos=15792|flags=__|side_data|side_data_type=MPEGTS Stream ID|id=224 |data_hash=CRC32:27b943ef packet|codec_type=video|stream_index=0|pts=564000|pts_time=6.266667|dts=564000|dts_time=6.266667|duration=6000|duration_time=0.066667|size=16|pos=16356|flags=__|data_hash=CRC32:f7116111 -stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|width=82|height=144|coded_width=82|coded_height=144|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=false|nal_length_size=0|id=0x100|r_frame_rate=15/1|avg_frame_rate=15/1|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=444000|duration=4.933333|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=74|extradata_hash=CRC32:e62cae27|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 +stream|index=0|codec_name=h264|profile=578|codec_type=video|codec_tag_string=[27][0][0][0]|codec_tag=0x001b|width=82|height=144|coded_width=82|coded_height=144|closed_captions=0|film_grain=0|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=41:72|pix_fmt=yuv420p|level=10|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=left|field_order=progressive|refs=1|is_avc=false|nal_length_size=0|id=0x100|r_frame_rate=15/1|avg_frame_rate=15/1|time_base=1/90000|start_pts=126000|start_time=1.400000|duration_ts=444000|duration=4.933333|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=N/A|nb_read_frames=N/A|nb_read_packets=74|extradata_size=35|extradata_hash=CRC32:e62cae27|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0 format|filename=h264small.ts|nb_streams=1|nb_programs=1|format_name=mpegts|start_time=1.400000|duration=4.933333|size=16544|bit_rate=26828|probe_score=50 diff --git a/tests/ref/lavf/mxf_opatom b/tests/ref/lavf/mxf_opatom index 61e755550b..e34cf2559e 100644 --- a/tests/ref/lavf/mxf_opatom +++ b/tests/ref/lavf/mxf_opatom @@ -1,3 +1,3 @@ -5d235c127ace64b1f4fe6c79a7ca8be6 *tests/data/lavf/lavf.mxf_opatom +aab6397829bd90f0c77a3f9fde53bb9c *tests/data/lavf/lavf.mxf_opatom 4717625 tests/data/lavf/lavf.mxf_opatom tests/data/lavf/lavf.mxf_opatom CRC=0xf55aa22a diff --git a/tests/ref/lavf/smjpeg b/tests/ref/lavf/smjpeg index 537c0847cb..94172a6b1e 100644 --- a/tests/ref/lavf/smjpeg +++ b/tests/ref/lavf/smjpeg @@ -1,3 +1,3 @@ 3fe90213ac4f5275eb85ad0a4e4bdb44 *tests/data/lavf/lavf.smjpeg 728642 tests/data/lavf/lavf.smjpeg -tests/data/lavf/lavf.smjpeg CRC=0x54bf6147 +tests/data/lavf/lavf.smjpeg CRC=0x75066147 diff --git a/tests/ref/seek/extra-mp4 b/tests/ref/seek/extra-mp4 index c17ce4003c..836f7c74ba 100644 --- a/tests/ref/seek/extra-mp4 +++ b/tests/ref/seek/extra-mp4 @@ -23,10 +23,10 @@ ret: 0 st: 0 flags:0 dts: 126.666667 pts: 126.766667 pos:13428716 size: ret: 0 st: 0 flags:0 dts: 126.700000 pts: 126.700000 pos:13431630 size: 781 ret: 0 st: 0 flags:0 dts: 126.733333 pts: 126.733333 pos:13432411 size: 817 ret: 0 st:-1 flags:0 ts: 50.576668 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 ret: 0 st:-1 flags:1 ts: 153.470835 ret: 0 st: 0 flags:1 dts: 151.966667 pts: 152.000000 pos:15705355 size:146924 ret: 0 st: 0 flags:0 dts: 152.000000 pts: 152.100000 pos:15852279 size: 1355 @@ -43,10 +43,10 @@ ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.033333 pos: 1470 size: 24 ret: 0 st: 0 flags:0 dts: 0.033333 pts: 0.066667 pos: 1494 size: 6779 ret: 0 st: 0 flags:0 dts: 0.066667 pts: 0.100000 pos: 8273 size: 11041 ret: 0 st:-1 flags:0 ts: 102.153336 -ret: 0 st: 0 flags:1 dts: 104.066667 pts: 104.100000 pos:11116461 size:112929 -ret: 0 st: 0 flags:0 dts: 104.100000 pts: 104.133333 pos:11229390 size: 585 -ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229975 size: 797 -ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11230772 size: 810 +ret: 0 st: 0 flags:1 dts: 104.100000 pts: 104.133333 pos:11116461 size:112929 +ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229390 size: 585 +ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11229975 size: 797 +ret: 0 st: 0 flags:0 dts: 104.200000 pts: 104.233333 pos:11230772 size: 810 ret: 0 st:-1 flags:1 ts: 25.047503 ret: 0 st: 0 flags:1 dts: 20.233333 pts: 20.266667 pos:2223959 size: 51823 ret: 0 st: 0 flags:0 dts: 20.266667 pts: 20.300000 pos:2275782 size: 488 @@ -58,10 +58,10 @@ ret: 0 st: 0 flags:0 dts: 131.266667 pts: 131.366667 pos:13790182 size: ret: 0 st: 0 flags:0 dts: 131.300000 pts: 131.300000 pos:13792531 size: 571 ret: 0 st: 0 flags:0 dts: 131.333333 pts: 131.333333 pos:13793102 size: 1190 ret: 0 st: 0 flags:1 ts: 50.835833 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 ret: 0 st:-1 flags:0 ts: 153.730004 ret: 0 st: 0 flags:1 dts: 157.033333 pts: 157.066667 pos:16225365 size: 82738 ret: 0 st: 0 flags:0 dts: 157.066667 pts: 157.166667 pos:16308103 size: 2273 @@ -93,10 +93,10 @@ ret: 0 st: 0 flags:0 dts: 127.866667 pts: 127.966667 pos:13581454 size: ret: 0 st: 0 flags:0 dts: 127.900000 pts: 127.900000 pos:13584390 size: 451 ret: 0 st: 0 flags:0 dts: 127.933333 pts: 127.933333 pos:13584841 size: 537 ret: 0 st: 0 flags:0 ts: 51.095011 -ret: 0 st: 0 flags:1 dts: 52.033333 pts: 52.066667 pos:6028050 size:115809 -ret: 0 st: 0 flags:0 dts: 52.066667 pts: 52.166667 pos:6143859 size: 1620 -ret: 0 st: 0 flags:0 dts: 52.100000 pts: 52.100000 pos:6145479 size: 92 -ret: 0 st: 0 flags:0 dts: 52.133333 pts: 52.133333 pos:6145571 size: 533 +ret: 0 st: 0 flags:1 dts: 52.066667 pts: 52.100000 pos:6028050 size:115809 +ret: 0 st: 0 flags:0 dts: 52.100000 pts: 52.200000 pos:6143859 size: 1620 +ret: 0 st: 0 flags:0 dts: 52.133333 pts: 52.133333 pos:6145479 size: 92 +ret: 0 st: 0 flags:0 dts: 52.166667 pts: 52.166667 pos:6145571 size: 533 ret: 0 st: 0 flags:1 ts: 153.989178 ret: 0 st: 0 flags:1 dts: 153.466667 pts: 153.500000 pos:15867700 size: 96169 ret: 0 st: 0 flags:0 dts: 153.500000 pts: 153.533333 pos:15963869 size: 785 @@ -113,10 +113,10 @@ ret: 0 st: 0 flags:0 dts: 0.000000 pts: 0.033333 pos: 1470 size: 24 ret: 0 st: 0 flags:0 dts: 0.033333 pts: 0.066667 pos: 1494 size: 6779 ret: 0 st: 0 flags:0 dts: 0.066667 pts: 0.100000 pos: 8273 size: 11041 ret: 0 st: 0 flags:0 ts: 102.671678 -ret: 0 st: 0 flags:1 dts: 104.066667 pts: 104.100000 pos:11116461 size:112929 -ret: 0 st: 0 flags:0 dts: 104.100000 pts: 104.133333 pos:11229390 size: 585 -ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229975 size: 797 -ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11230772 size: 810 +ret: 0 st: 0 flags:1 dts: 104.100000 pts: 104.133333 pos:11116461 size:112929 +ret: 0 st: 0 flags:0 dts: 104.133333 pts: 104.166667 pos:11229390 size: 585 +ret: 0 st: 0 flags:0 dts: 104.166667 pts: 104.200000 pos:11229975 size: 797 +ret: 0 st: 0 flags:0 dts: 104.200000 pts: 104.233333 pos:11230772 size: 810 ret: 0 st: 0 flags:1 ts: 25.565844 ret: 0 st: 0 flags:1 dts: 25.300000 pts: 25.333333 pos:2607246 size: 40273 ret: 0 st: 0 flags:0 dts: 25.333333 pts: 25.433333 pos:2647519 size: 2959 @@ -128,7 +128,7 @@ ret: 0 st: 0 flags:0 dts: 131.266667 pts: 131.366667 pos:13790182 size: ret: 0 st: 0 flags:0 dts: 131.300000 pts: 131.300000 pos:13792531 size: 571 ret: 0 st: 0 flags:0 dts: 131.333333 pts: 131.333333 pos:13793102 size: 1190 ret: 0 st:-1 flags:1 ts: 51.354175 -ret: 0 st: 0 flags:1 dts: 50.600000 pts: 50.633333 pos:5858254 size: 67903 -ret: 0 st: 0 flags:0 dts: 50.633333 pts: 50.733333 pos:5926157 size: 1307 -ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.666667 pos:5927464 size: 150 -ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927614 size: 176 +ret: 0 st: 0 flags:1 dts: 50.633333 pts: 50.666667 pos:5858254 size: 67903 +ret: 0 st: 0 flags:0 dts: 50.666667 pts: 50.766667 pos:5926157 size: 1307 +ret: 0 st: 0 flags:0 dts: 50.700000 pts: 50.700000 pos:5927464 size: 150 +ret: 0 st: 0 flags:0 dts: 50.733333 pts: 50.733333 pos:5927614 size: 176 diff --git a/tools/target_dec_fuzzer.c b/tools/target_dec_fuzzer.c index 8800231691..13766d22b9 100644 --- a/tools/target_dec_fuzzer.c +++ b/tools/target_dec_fuzzer.c @@ -160,17 +160,20 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { case AV_CODEC_ID_DIRAC: maxpixels /= 8192; 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_FLV1: maxpixels /= 1024; break; case AV_CODEC_ID_G2M: maxpixels /= 1024; break; + case AV_CODEC_ID_GEM: maxpixels /= 512; break; case AV_CODEC_ID_GDV: maxpixels /= 512; break; case AV_CODEC_ID_GIF: maxpixels /= 16; break; case AV_CODEC_ID_H264: maxpixels /= 256; break; case AV_CODEC_ID_HAP: maxpixels /= 128; break; case AV_CODEC_ID_HEVC: maxpixels /= 16384; break; case AV_CODEC_ID_HNM4_VIDEO: maxpixels /= 128; break; + case AV_CODEC_ID_HQ_HQA: maxpixels /= 128; break; case AV_CODEC_ID_IFF_ILBM: maxpixels /= 128; break; case AV_CODEC_ID_INDEO4: maxpixels /= 128; break; case AV_CODEC_ID_INTERPLAY_ACM: maxsamples /= 16384; break; @@ -184,11 +187,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 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_MXPEG: maxpixels /= 128; break; case AV_CODEC_ID_OPUS: maxsamples /= 16384; break; case AV_CODEC_ID_PNG: maxpixels /= 128; break; case AV_CODEC_ID_APNG: maxpixels /= 128; break; case AV_CODEC_ID_QTRLE: maxpixels /= 16; break; case AV_CODEC_ID_PAF_VIDEO: maxpixels /= 16; break; + case AV_CODEC_ID_PRORES: maxpixels /= 256; break; case AV_CODEC_ID_RASC: maxpixels /= 16; break; case AV_CODEC_ID_SANM: maxpixels /= 16; break; case AV_CODEC_ID_SCPR: maxpixels /= 32; break; @@ -391,8 +396,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { decode_more = ret >= 0; if(!decode_more) { ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); - if (it > 20 || ec_pixels > 4 * ctx->max_pixels) + if (it > 20 || ec_pixels > 4 * ctx->max_pixels) { ctx->error_concealment = 0; + ctx->debug &= ~(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE); + } if (ec_pixels > maxpixels) goto maximums_reached; } @@ -405,8 +412,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { int ret = decode_handler(ctx, frame, &got_frame, avpkt); ec_pixels += (ctx->width + 32LL) * (ctx->height + 32LL); - if (it > 20 || ec_pixels > 4 * ctx->max_pixels) + if (it > 20 || ec_pixels > 4 * ctx->max_pixels) { ctx->error_concealment = 0; + ctx->debug &= ~(FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE); + } if (ec_pixels > maxpixels) goto maximums_reached;